Stair56E UART project

This commit is contained in:
2026-08-05 19:07:52 +08:00
parent 7ca1af130d
commit f5654b70cc
2500 changed files with 619007 additions and 282610 deletions
+17 -17
View File
@@ -1,17 +1,17 @@
# sbc decoder
SBC_DECODER += \
alloc.c \
bitalloc.c \
bitalloc-sbc.c \
bitstream-decode.c \
decoder-oina.c \
decoder-private.c \
decoder-sbc.c \
dequant.c \
framing.c \
framing-sbc.c \
oi_codec_version.c \
synthesis-sbc.c \
synthesis-dct8.c \
synthesis-8-generated.c \
# sbc decoder
SBC_DECODER += \
alloc.c \
bitalloc.c \
bitalloc-sbc.c \
bitstream-decode.c \
decoder-oina.c \
decoder-private.c \
decoder-sbc.c \
dequant.c \
framing.c \
framing-sbc.c \
oi_codec_version.c \
synthesis-sbc.c \
synthesis-dct8.c \
synthesis-8-generated.c \
+86 -86
View File
@@ -1,86 +1,86 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_ASSERT_H
#define _OI_ASSERT_H
/** @file
This file provides macros and functions for compile-time and run-time assertions.
When the OI_DEBUG preprocessor value is defined, the macro OI_ASSERT is compiled into
the program, providing for a runtime assertion failure check.
C_ASSERT is a macro that can be used to perform compile time checks.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** \addtogroup Debugging Debugging APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef OI_DEBUG
/** The macro OI_ASSERT takes a condition argument. If the asserted condition
does not evaluate to true, the OI_ASSERT macro calls the host-dependent function,
OI_AssertFail(), which reports the failure and generates a runtime error.
*/
void OI_AssertFail(const char * file, int line, const char * reason);
#define OI_ASSERT(condition) \
{ if (!(condition)) OI_AssertFail((const char *)__FILE__, __LINE__, #condition); }
#define OI_ASSERT_FAIL(msg) \
{ OI_AssertFail((const char *)__FILE__, __LINE__, (const char *)msg); }
#else
#define OI_ASSERT(condition)
#define OI_ASSERT_FAIL(msg)
#endif
/**
C_ASSERT() can be used to perform many compile-time assertions: type sizes, field offsets, etc.
An assertion failure results in compile time error C2118: negative subscript.
Unfortunately, this elegant macro doesn't work with GCC, so it's all commented out
for now. Perhaps later.....
*/
#ifndef C_ASSERT
// #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
// #define C_ASSERT(e)
#endif
/*****************************************************************************/
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_ASSERT_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_ASSERT_H
#define _OI_ASSERT_H
/** @file
This file provides macros and functions for compile-time and run-time assertions.
When the OI_DEBUG preprocessor value is defined, the macro OI_ASSERT is compiled into
the program, providing for a runtime assertion failure check.
C_ASSERT is a macro that can be used to perform compile time checks.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** \addtogroup Debugging Debugging APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef OI_DEBUG
/** The macro OI_ASSERT takes a condition argument. If the asserted condition
does not evaluate to true, the OI_ASSERT macro calls the host-dependent function,
OI_AssertFail(), which reports the failure and generates a runtime error.
*/
void OI_AssertFail(const char * file, int line, const char * reason);
#define OI_ASSERT(condition) \
{ if (!(condition)) OI_AssertFail((const char *)__FILE__, __LINE__, #condition); }
#define OI_ASSERT_FAIL(msg) \
{ OI_AssertFail((const char *)__FILE__, __LINE__, (const char *)msg); }
#else
#define OI_ASSERT(condition)
#define OI_ASSERT_FAIL(msg)
#endif
/**
C_ASSERT() can be used to perform many compile-time assertions: type sizes, field offsets, etc.
An assertion failure results in compile time error C2118: negative subscript.
Unfortunately, this elegant macro doesn't work with GCC, so it's all commented out
for now. Perhaps later.....
*/
#ifndef C_ASSERT
// #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
// #define C_ASSERT(e)
#endif
/*****************************************************************************/
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_ASSERT_H */
+123 -123
View File
@@ -1,123 +1,123 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_BITSTREAM_H
#define _OI_BITSTREAM_H
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Function prototypes and macro definitions for manipulating input and output
bitstreams.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_stddefs.h"
INLINE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs, const OI_BYTE *buffer);
INLINE void OI_BITSTREAM_WriteInit(OI_BITSTREAM *bs, OI_BYTE *buffer);
INLINE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits);
INLINE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs);
INLINE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs);
INLINE void OI_BITSTREAM_WriteUINT(OI_BITSTREAM *bs,
OI_UINT16 value,
OI_UINT bits);
/*
* Use knowledge that the bitstream is aligned to optimize the write of a byte
*/
PRIVATE void OI_BITSTREAM_WriteUINT8Aligned(OI_BITSTREAM *bs,
OI_UINT8 datum);
/*
* Use knowledge that the bitstream is aligned to optimize the write pair of nibbles
*/
PRIVATE void OI_BITSTREAM_Write2xUINT4Aligned(OI_BITSTREAM *bs,
OI_UINT8 datum1,
OI_UINT8 datum2);
/** Internally the bitstream looks ahead in the stream. When
* OI_SBC_ReadScalefactors() goes to temporarily break the abstraction, it will
* need to know where the "logical" pointer is in the stream.
*/
#define OI_BITSTREAM_GetWritePtr(bs) ((bs)->ptr.w - 3)
#define OI_BITSTREAM_GetReadPtr(bs) ((bs)->ptr.r - 3)
/** This is declared here as a macro because decoder.c breaks the bitsream
* encapsulation for efficiency reasons.
*/
#define OI_BITSTREAM_READUINT(result, bits, ptr, value, bitPtr) \
do { \
OI_ASSERT((bits) <= 16); \
OI_ASSERT((bitPtr) < 16); \
OI_ASSERT((bitPtr) >= 8); \
\
result = (value) << (bitPtr); \
result >>= 32 - (bits); \
\
bitPtr += (bits); \
while (bitPtr >= 16) { \
value = (((value) << 8) | *ptr++) & 0xffffffff; \
bitPtr -= 8; \
} \
OI_ASSERT((bits == 0) || (result < (1u << (bits)))); \
} while (0)
#define OI_BITSTREAM_WRITEUINT(ptr, value, bitPtr, datum, bits) \
do {\
bitPtr -= bits;\
value |= datum << bitPtr;\
\
while (bitPtr <= 16) {\
bitPtr += 8;\
*ptr++ = (OI_UINT8)(value >> 24);\
value <<= 8;\
}\
} while (0)
#define OI_BITSTREAM_WRITEFLUSH(ptr, value, bitPtr) \
do {\
while (bitPtr < 32) {\
bitPtr += 8;\
*ptr++ = (OI_UINT8)(value >> 24);\
value <<= 8;\
}\
} while (0)
/**
@}
*/
#endif /* _OI_BITSTREAM_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_BITSTREAM_H
#define _OI_BITSTREAM_H
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Function prototypes and macro definitions for manipulating input and output
bitstreams.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_stddefs.h"
INLINE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs, const OI_BYTE *buffer);
INLINE void OI_BITSTREAM_WriteInit(OI_BITSTREAM *bs, OI_BYTE *buffer);
INLINE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits);
INLINE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs);
INLINE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs);
INLINE void OI_BITSTREAM_WriteUINT(OI_BITSTREAM *bs,
OI_UINT16 value,
OI_UINT bits);
/*
* Use knowledge that the bitstream is aligned to optimize the write of a byte
*/
PRIVATE void OI_BITSTREAM_WriteUINT8Aligned(OI_BITSTREAM *bs,
OI_UINT8 datum);
/*
* Use knowledge that the bitstream is aligned to optimize the write pair of nibbles
*/
PRIVATE void OI_BITSTREAM_Write2xUINT4Aligned(OI_BITSTREAM *bs,
OI_UINT8 datum1,
OI_UINT8 datum2);
/** Internally the bitstream looks ahead in the stream. When
* OI_SBC_ReadScalefactors() goes to temporarily break the abstraction, it will
* need to know where the "logical" pointer is in the stream.
*/
#define OI_BITSTREAM_GetWritePtr(bs) ((bs)->ptr.w - 3)
#define OI_BITSTREAM_GetReadPtr(bs) ((bs)->ptr.r - 3)
/** This is declared here as a macro because decoder.c breaks the bitsream
* encapsulation for efficiency reasons.
*/
#define OI_BITSTREAM_READUINT(result, bits, ptr, value, bitPtr) \
do { \
OI_ASSERT((bits) <= 16); \
OI_ASSERT((bitPtr) < 16); \
OI_ASSERT((bitPtr) >= 8); \
\
result = (value) << (bitPtr); \
result >>= 32 - (bits); \
\
bitPtr += (bits); \
while (bitPtr >= 16) { \
value = (((value) << 8) | *ptr++) & 0xffffffff; \
bitPtr -= 8; \
} \
OI_ASSERT((bits == 0) || (result < (1u << (bits)))); \
} while (0)
#define OI_BITSTREAM_WRITEUINT(ptr, value, bitPtr, datum, bits) \
do {\
bitPtr -= bits;\
value |= datum << bitPtr;\
\
while (bitPtr <= 16) {\
bitPtr += 8;\
*ptr++ = (OI_UINT8)(value >> 24);\
value <<= 8;\
}\
} while (0)
#define OI_BITSTREAM_WRITEFLUSH(ptr, value, bitPtr) \
do {\
while (bitPtr < 32) {\
bitPtr += 8;\
*ptr++ = (OI_UINT8)(value >> 24);\
value <<= 8;\
}\
} while (0)
/**
@}
*/
#endif /* _OI_BITSTREAM_H */
+229 -229
View File
@@ -1,229 +1,229 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_BT_SPEC_H
#define _OI_BT_SPEC_H
/**
* @file
*
* This file contains common definitions from the Bluetooth specification.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/** The maximum number of active slaves in a piconet. */
#define OI_BT_MAX_ACTIVE_SLAVES 7
/** the number of bytes in a Bluetooth device address (BD_ADDR) */
#define OI_BD_ADDR_BYTE_SIZE 6
/**
* 48-bit Bluetooth device address
*
* Because 48-bit integers may not be supported on all platforms, the
* address is defined as an array of bytes. This array is big-endian,
* meaning that
* - array[0] contains bits 47-40,
* - array[1] contains bits 39-32,
* - array[2] contains bits 31-24,
* - array[3] contains bits 23-16,
* - array[4] contains bits 15-8, and
* - array[5] contains bits 7-0.
*/
typedef struct {
OI_UINT8 addr[OI_BD_ADDR_BYTE_SIZE] ; /**< Bluetooth device address represented as an array of 8-bit values */
} OI_BD_ADDR ;
/**
* @name Data types for working with UUIDs
* UUIDs are 16 bytes (128 bits).
*
* To avoid having to pass around 128-bit values all the time, 32-bit and 16-bit
* UUIDs are defined, along with a mapping from the shorter versions to the full
* version.
*
* @{
*/
/**
* 16-bit representation of a 128-bit UUID
*/
typedef OI_UINT16 OI_UUID16;
/**
* 32-bit representation of a 128-bit UUID
*/
typedef OI_UINT32 OI_UUID32;
/**
* number of bytes in a 128 bit UUID
*/
#define OI_BT_UUID128_SIZE 16
/**
* number of bytes in IPv6 style addresses
*/
#define OI_BT_IPV6ADDR_SIZE 16
/**
* type definition for a 128-bit UUID
*
* To simplify conversion between 128-bit UUIDs and 16-bit and 32-bit UUIDs,
* the most significant 32 bits are stored with the same endian-ness as is
* native on the target (local) device. The remainder of the 128-bit UUID is
* stored as bytes in big-endian order.
*/
typedef struct {
OI_UINT32 ms32bits; /**< most significant 32 bits of 128-bit UUID */
OI_UINT8 base[OI_BT_UUID128_SIZE - sizeof(OI_UINT32)]; /**< remainder of 128-bit UUID, array of 8-bit values */
} OI_UUID128;
/** @} */
/** number of bytes in a link key */
#define OI_BT_LINK_KEY_SIZE 16
/**
* type definition for a baseband link key
*
* Because 128-bit integers may not be supported on all platforms, we define
* link keys as an array of bytes. Unlike the Bluetooth device address,
* the link key is stored in little-endian order, meaning that
* - array[0] contains bits 0 - 7,
* - array[1] contains bits 8 - 15,
* - array[2] contains bits 16 - 23,
* - array[3] contains bits 24 - 31,
* - array[4] contains bits 32 - 39,
* - array[5] contains bits 40 - 47,
* - array[6] contains bits 48 - 55,
* - array[7] contains bits 56 - 63,
* - array[8] contains bits 64 - 71,
* - array[9] contains bits 72 - 79,
* - array[10] contains bits 80 - 87,
* - array[11] contains bits 88 - 95,
* - array[12] contains bits 96 - 103,
* - array[13] contains bits 104- 111,
* - array[14] contains bits 112- 119, and
* - array[15] contains bits 120- 127.
*/
typedef struct {
OI_UINT8 key[OI_BT_LINK_KEY_SIZE] ; /**< link key represented as an array of 8-bit values */
} OI_LINK_KEY ;
/** Out-of-band data size - C and R values are 16-bytes each */
#define OI_BT_OOB_NUM_BYTES 16
typedef struct {
OI_UINT8 value[OI_BT_OOB_NUM_BYTES] ; /**< same struct used for C and R values */
} OI_OOB_DATA ;
/**
* link key types
*/
typedef enum {
OI_LINK_KEY_TYPE_COMBO = 0, /**< combination key */
OI_LINK_KEY_TYPE_LOCAL_UNIT = 1, /**< local unit key */
OI_LINK_KEY_TYPE_REMOTE_UNIT = 2, /**< remote unit key */
OI_LINK_KEY_TYPE_DEBUG_COMBO = 3, /**< debug combination key */
OI_LINK_KEY_TYPE_UNAUTHENTICATED = 4, /**< Unauthenticated */
OI_LINK_KEY_TYPE_AUTHENTICATED = 5, /**< Authenticated */
OI_LINK_KEY_TYPE_CHANGED_COMBO = 6 /**< Changed */
} OI_BT_LINK_KEY_TYPE ;
/** amount of space allocated for a PIN (personal indentification number) in bytes */
#define OI_BT_PIN_CODE_SIZE 16
/** data type for a PIN (PINs are treated as strings, so endianness does not apply.) */
typedef struct {
OI_UINT8 pin[OI_BT_PIN_CODE_SIZE] ; /**< PIN represented as an array of 8-bit values */
} OI_PIN_CODE ;
/** maximum number of SCO connections per device, which is 3 as of version 2.0+EDR
of the Bluetooth specification (see sec 4.3 of vol 2 part B) */
#define OI_BT_MAX_SCO_CONNECTIONS 3
/** data type for clock offset */
typedef OI_UINT16 OI_BT_CLOCK_OFFSET ;
/** data type for a LM handle */
typedef OI_UINT16 OI_HCI_LM_HANDLE;
/** opaque data type for a SCO or ACL connection handle */
typedef struct _OI_HCI_CONNECTION *OI_HCI_CONNECTION_HANDLE;
/** data type for HCI Error Code, as defined in oi_hcispec.h */
typedef OI_UINT8 OI_HCI_ERROR_CODE ;
/**
* The Bluetooth device type is indicated by a 24-bit bitfield, represented as a
* 32-bit number in the stack. The bit layout and values for device class are specified
* in the file oi_bt_assigned_nos.h and in the Bluetooth "Assigned Numbers" specification
* at http://www.bluetooth.org/assigned-numbers/.
*/
typedef OI_UINT32 OI_BT_DEVICE_CLASS ;
#define OI_BT_DEV_CLASS_FORMAT_MASK 0x000003 /**< Bits 0-1 contain format type. */
#define OI_BT_DEV_CLASS_MINOR_DEVICE_MASK 0x0000FC /**< Bits 2-7 contain minor device class value. */
#define OI_BT_DEV_CLASS_MAJOR_DEVICE_MASK 0x001F00 /**< Bits 8-12 contain major device class value. */
#define OI_BT_DEV_CLASS_MAJOR_SERVICE_MASK 0xFFE000 /**< Bits 13-23 contain major service class value. */
/** There is currently only one device class format defined, type 00. */
#define OI_BT_DEV_CLASS_FORMAT_TYPE 00
/** Bit 13 in device class indicates limited discoverability mode (GAP v2.0+EDR, section 4.1.2.2) */
#define OI_BT_DEV_CLASS_LIMITED_DISCO_BIT BIT13
/** macro to test validity of the Device Class Format */
#define OI_BT_VALID_DEVICE_CLASS_FORMAT(class) (OI_BT_DEV_CLASS_FORMAT_TYPE == ((class) & OI_BT_DEV_CLASS_FORMAT_MASK))
/** the time between baseband clock ticks, currently 625 microseconds (one slot) */
#define OI_BT_TICK 625
/** some macros to convert to/from baseband clock ticks - use no floating point! */
#define OI_SECONDS_TO_BT_TICKS(secs) ((secs)*1600)
#define OI_BT_TICKS_TO_SECONDS(ticks) ((ticks)/1600)
#define OI_MSECS_TO_BT_TICKS(msecs) (((msecs)*8)/5)
#define OI_BT_TICKS_TO_MSECS(ticks) (((ticks)*5)/8)
/** EIR byte order */
#define OI_EIR_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER
#ifdef __cplusplus
}
#endif
/**@}*/
/*****************************************************************************/
#endif /* _OI_BT_SPEC_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_BT_SPEC_H
#define _OI_BT_SPEC_H
/**
* @file
*
* This file contains common definitions from the Bluetooth specification.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/** The maximum number of active slaves in a piconet. */
#define OI_BT_MAX_ACTIVE_SLAVES 7
/** the number of bytes in a Bluetooth device address (BD_ADDR) */
#define OI_BD_ADDR_BYTE_SIZE 6
/**
* 48-bit Bluetooth device address
*
* Because 48-bit integers may not be supported on all platforms, the
* address is defined as an array of bytes. This array is big-endian,
* meaning that
* - array[0] contains bits 47-40,
* - array[1] contains bits 39-32,
* - array[2] contains bits 31-24,
* - array[3] contains bits 23-16,
* - array[4] contains bits 15-8, and
* - array[5] contains bits 7-0.
*/
typedef struct {
OI_UINT8 addr[OI_BD_ADDR_BYTE_SIZE] ; /**< Bluetooth device address represented as an array of 8-bit values */
} OI_BD_ADDR ;
/**
* @name Data types for working with UUIDs
* UUIDs are 16 bytes (128 bits).
*
* To avoid having to pass around 128-bit values all the time, 32-bit and 16-bit
* UUIDs are defined, along with a mapping from the shorter versions to the full
* version.
*
* @{
*/
/**
* 16-bit representation of a 128-bit UUID
*/
typedef OI_UINT16 OI_UUID16;
/**
* 32-bit representation of a 128-bit UUID
*/
typedef OI_UINT32 OI_UUID32;
/**
* number of bytes in a 128 bit UUID
*/
#define OI_BT_UUID128_SIZE 16
/**
* number of bytes in IPv6 style addresses
*/
#define OI_BT_IPV6ADDR_SIZE 16
/**
* type definition for a 128-bit UUID
*
* To simplify conversion between 128-bit UUIDs and 16-bit and 32-bit UUIDs,
* the most significant 32 bits are stored with the same endian-ness as is
* native on the target (local) device. The remainder of the 128-bit UUID is
* stored as bytes in big-endian order.
*/
typedef struct {
OI_UINT32 ms32bits; /**< most significant 32 bits of 128-bit UUID */
OI_UINT8 base[OI_BT_UUID128_SIZE - sizeof(OI_UINT32)]; /**< remainder of 128-bit UUID, array of 8-bit values */
} OI_UUID128;
/** @} */
/** number of bytes in a link key */
#define OI_BT_LINK_KEY_SIZE 16
/**
* type definition for a baseband link key
*
* Because 128-bit integers may not be supported on all platforms, we define
* link keys as an array of bytes. Unlike the Bluetooth device address,
* the link key is stored in little-endian order, meaning that
* - array[0] contains bits 0 - 7,
* - array[1] contains bits 8 - 15,
* - array[2] contains bits 16 - 23,
* - array[3] contains bits 24 - 31,
* - array[4] contains bits 32 - 39,
* - array[5] contains bits 40 - 47,
* - array[6] contains bits 48 - 55,
* - array[7] contains bits 56 - 63,
* - array[8] contains bits 64 - 71,
* - array[9] contains bits 72 - 79,
* - array[10] contains bits 80 - 87,
* - array[11] contains bits 88 - 95,
* - array[12] contains bits 96 - 103,
* - array[13] contains bits 104- 111,
* - array[14] contains bits 112- 119, and
* - array[15] contains bits 120- 127.
*/
typedef struct {
OI_UINT8 key[OI_BT_LINK_KEY_SIZE] ; /**< link key represented as an array of 8-bit values */
} OI_LINK_KEY ;
/** Out-of-band data size - C and R values are 16-bytes each */
#define OI_BT_OOB_NUM_BYTES 16
typedef struct {
OI_UINT8 value[OI_BT_OOB_NUM_BYTES] ; /**< same struct used for C and R values */
} OI_OOB_DATA ;
/**
* link key types
*/
typedef enum {
OI_LINK_KEY_TYPE_COMBO = 0, /**< combination key */
OI_LINK_KEY_TYPE_LOCAL_UNIT = 1, /**< local unit key */
OI_LINK_KEY_TYPE_REMOTE_UNIT = 2, /**< remote unit key */
OI_LINK_KEY_TYPE_DEBUG_COMBO = 3, /**< debug combination key */
OI_LINK_KEY_TYPE_UNAUTHENTICATED = 4, /**< Unauthenticated */
OI_LINK_KEY_TYPE_AUTHENTICATED = 5, /**< Authenticated */
OI_LINK_KEY_TYPE_CHANGED_COMBO = 6 /**< Changed */
} OI_BT_LINK_KEY_TYPE ;
/** amount of space allocated for a PIN (personal indentification number) in bytes */
#define OI_BT_PIN_CODE_SIZE 16
/** data type for a PIN (PINs are treated as strings, so endianness does not apply.) */
typedef struct {
OI_UINT8 pin[OI_BT_PIN_CODE_SIZE] ; /**< PIN represented as an array of 8-bit values */
} OI_PIN_CODE ;
/** maximum number of SCO connections per device, which is 3 as of version 2.0+EDR
of the Bluetooth specification (see sec 4.3 of vol 2 part B) */
#define OI_BT_MAX_SCO_CONNECTIONS 3
/** data type for clock offset */
typedef OI_UINT16 OI_BT_CLOCK_OFFSET ;
/** data type for a LM handle */
typedef OI_UINT16 OI_HCI_LM_HANDLE;
/** opaque data type for a SCO or ACL connection handle */
typedef struct _OI_HCI_CONNECTION *OI_HCI_CONNECTION_HANDLE;
/** data type for HCI Error Code, as defined in oi_hcispec.h */
typedef OI_UINT8 OI_HCI_ERROR_CODE ;
/**
* The Bluetooth device type is indicated by a 24-bit bitfield, represented as a
* 32-bit number in the stack. The bit layout and values for device class are specified
* in the file oi_bt_assigned_nos.h and in the Bluetooth "Assigned Numbers" specification
* at http://www.bluetooth.org/assigned-numbers/.
*/
typedef OI_UINT32 OI_BT_DEVICE_CLASS ;
#define OI_BT_DEV_CLASS_FORMAT_MASK 0x000003 /**< Bits 0-1 contain format type. */
#define OI_BT_DEV_CLASS_MINOR_DEVICE_MASK 0x0000FC /**< Bits 2-7 contain minor device class value. */
#define OI_BT_DEV_CLASS_MAJOR_DEVICE_MASK 0x001F00 /**< Bits 8-12 contain major device class value. */
#define OI_BT_DEV_CLASS_MAJOR_SERVICE_MASK 0xFFE000 /**< Bits 13-23 contain major service class value. */
/** There is currently only one device class format defined, type 00. */
#define OI_BT_DEV_CLASS_FORMAT_TYPE 00
/** Bit 13 in device class indicates limited discoverability mode (GAP v2.0+EDR, section 4.1.2.2) */
#define OI_BT_DEV_CLASS_LIMITED_DISCO_BIT BIT13
/** macro to test validity of the Device Class Format */
#define OI_BT_VALID_DEVICE_CLASS_FORMAT(class) (OI_BT_DEV_CLASS_FORMAT_TYPE == ((class) & OI_BT_DEV_CLASS_FORMAT_MASK))
/** the time between baseband clock ticks, currently 625 microseconds (one slot) */
#define OI_BT_TICK 625
/** some macros to convert to/from baseband clock ticks - use no floating point! */
#define OI_SECONDS_TO_BT_TICKS(secs) ((secs)*1600)
#define OI_BT_TICKS_TO_SECONDS(ticks) ((ticks)/1600)
#define OI_MSECS_TO_BT_TICKS(msecs) (((msecs)*8)/5)
#define OI_BT_TICKS_TO_MSECS(ticks) (((ticks)*5)/8)
/** EIR byte order */
#define OI_EIR_BYTE_ORDER OI_LITTLE_ENDIAN_BYTE_ORDER
#ifdef __cplusplus
}
#endif
/**@}*/
/*****************************************************************************/
#endif /* _OI_BT_SPEC_H */
+497 -497
View File
@@ -1,497 +1,497 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#ifndef _OI_CODEC_SBC_CORE_H
#define _OI_CODEC_SBC_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/**
@file
Declarations of codec functions, data types, and macros.
@ingroup codec_lib
*/
/**
@addtogroup codec_lib
@{
*/
/* Non-BM3 users of of the codec must include oi_codec_sbc_bm3defs.h prior to
* including this file, or else these includes will fail because the BM3 SDK is
* not in the include path */
#ifndef _OI_CODEC_SBC_BM3DEFS_H
#include "oi_stddefs.h"
#include "oi_status.h"
#endif
#include <stdint.h>
#define SBC_MAX_CHANNELS 2
#define SBC_MAX_BANDS 8
#define SBC_MAX_BLOCKS 16
#define SBC_MIN_BITPOOL 2 /**< Minimum size of the bit allocation pool used to encode the stream */
#define SBC_MAX_BITPOOL 250 /**< Maximum size of the bit allocation pool used to encode the stream */
#define SBC_MAX_ONE_CHANNEL_BPS 320000
#define SBC_MAX_TWO_CHANNEL_BPS 512000
#define SBC_WBS_BITRATE 62000
#define SBC_WBS_BITPOOL 27
#define SBC_WBS_NROF_BLOCKS 16
#define SBC_WBS_FRAME_LEN 62
#define SBC_WBS_SAMPLES_PER_FRAME 128
#define SBC_HEADER_LEN 4
#define SBC_MAX_FRAME_LEN (SBC_HEADER_LEN + \
((SBC_MAX_BANDS * SBC_MAX_CHANNELS / 2) + \
((SBC_MAX_BANDS + (SBC_MAX_BLOCKS * SBC_MAX_BITPOOL) + 7)/8)))
#define SBC_MAX_SAMPLES_PER_FRAME (SBC_MAX_BANDS * SBC_MAX_BLOCKS)
#define SBC_MAX_SCALEFACTOR_BYTES ((4*(SBC_MAX_CHANNELS * SBC_MAX_BANDS) + 7)/8)
#define OI_SBC_SYNCWORD 0x9c
#define OI_SBC_ENHANCED_SYNCWORD 0x9d
/**@name Sampling frequencies */
/**@{*/
#define SBC_FREQ_16000 0 /**< The sampling frequency is 16 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_32000 1 /**< The sampling frequency is 32 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_44100 2 /**< The sampling frequency is 44.1 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_48000 3 /**< The sampling frequency is 48 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Channel modes */
/**@{*/
#define SBC_MONO 0 /**< The mode of the encoded channel is mono. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_DUAL_CHANNEL 1 /**< The mode of the encoded channel is dual-channel. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_STEREO 2 /**< The mode of the encoded channel is stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_JOINT_STEREO 3 /**< The mode of the encoded channel is joint stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Subbands */
/**@{*/
#define SBC_SUBBANDS_4 0 /**< The encoded stream has 4 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure()*/
#define SBC_SUBBANDS_8 1 /**< The encoded stream has 8 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Block lengths */
/**@{*/
#define SBC_BLOCKS_4 0 /**< A block size of 4 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_8 1 /**< A block size of 8 blocks was used to encode the stream is. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_12 2 /**< A block size of 12 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_16 3 /**< A block size of 16 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Bit allocation methods */
/**@{*/
#define SBC_LOUDNESS 0 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_SNR 1 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**
@}
@addtogroup codec_internal
@{
*/
typedef OI_INT16 SBC_BUFFER_T;
/** Used internally. */
typedef struct {
OI_UINT16 frequency; /**< The sampling frequency. Input parameter. */
OI_UINT8 freqIndex;
OI_UINT8 nrof_blocks; /**< The block size used to encode the stream. Input parameter. */
OI_UINT8 blocks;
OI_UINT8 nrof_subbands; /**< The number of subbands of the encoded stream. Input parameter. */
OI_UINT8 subbands;
OI_UINT8 mode; /**< The mode of the encoded channel. Input parameter. */
OI_UINT8 nrof_channels; /**< The number of channels of the encoded stream. */
OI_UINT8 alloc; /**< The bit allocation method. Input parameter. */
OI_UINT8 bitpool; /**< Size of the bit allocation pool used to encode the stream. Input parameter. */
OI_UINT8 crc; /**< Parity check byte used for error detection. */
OI_UINT8 join; /**< Whether joint stereo has been used. */
OI_UINT8 enhanced;
OI_UINT8 min_bitpool; /**< This value is only used when encoding. SBC_MAX_BITPOOL if variable
bitpools are disallowed, otherwise the minimum bitpool size that will
be used by the bit allocator. */
OI_UINT8 cachedInfo; /**< Information about the previous frame */
/* BK4BTSTACK_CHANGE START */
OI_UINT8 reserved_for_future_use[2];
OI_UINT8 mSBCEnabled; // default 0
/* BK4BTSTACK_CHANGE END */
} OI_CODEC_SBC_FRAME_INFO;
/** Used internally. */
typedef struct {
const OI_CHAR *codecInfo;
OI_CODEC_SBC_FRAME_INFO frameInfo;
OI_INT8 scale_factor[SBC_MAX_CHANNELS*SBC_MAX_BANDS];
OI_UINT32 frameCount;
OI_INT32 *subdata;
SBC_BUFFER_T *filterBuffer[SBC_MAX_CHANNELS];
OI_INT32 filterBufferLen;
OI_UINT filterBufferOffset;
union {
OI_UINT8 uint8[SBC_MAX_CHANNELS*SBC_MAX_BANDS];
OI_UINT32 uint32[SBC_MAX_CHANNELS*SBC_MAX_BANDS/4];
} bits;
OI_UINT8 maxBitneed; /**< Running maximum bitneed */
OI_BYTE formatByte;
OI_UINT8 pcmStride;
OI_UINT8 maxChannels;
} OI_CODEC_SBC_COMMON_CONTEXT;
/*
* A smaller value reduces RAM usage at the expense of increased CPU usage. Values in the range
* 27..50 are recommended, beyond 50 there is a diminishing return on reduced CPU usage.
*/
#define SBC_CODEC_MIN_FILTER_BUFFERS 16
#define SBC_CODEC_FAST_FILTER_BUFFERS 27
/* Expands to the number of OI_UINT32s needed to ensure enough memory to encode
* or decode streams of numChannels channels, using numBuffers buffers.
* Example:
* OI_UINT32 decoderData[CODEC_DATA_WORDS(SBC_MAX_CHANNELS, SBC_DECODER_FAST_SYNTHESIS_BUFFERS)];
* */
#define CODEC_DATA_WORDS(numChannels, numBuffers) \
((\
(sizeof(OI_INT32) * SBC_MAX_BLOCKS * numChannels * SBC_MAX_BANDS) \
+ (sizeof(SBC_BUFFER_T) * SBC_MAX_CHANNELS * SBC_MAX_BANDS * numBuffers) \
+ (sizeof (OI_UINT32) - 1) \
) / sizeof(OI_UINT32))
/** Opaque parameter to decoding functions; maintains decoder context. */
typedef struct {
OI_CODEC_SBC_COMMON_CONTEXT common;
OI_UINT8 limitFrameFormat; /* Boolean, set by OI_CODEC_SBC_DecoderLimit() */
OI_UINT8 restrictSubbands;
OI_UINT8 enhancedEnabled;
OI_UINT8 bufferedBlocks;
} OI_CODEC_SBC_DECODER_CONTEXT;
typedef struct {
OI_UINT32 data[CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)];
} OI_CODEC_SBC_CODEC_DATA_MONO;
typedef struct {
OI_UINT32 data[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
} OI_CODEC_SBC_CODEC_DATA_STEREO;
/**
@}
@addtogroup codec_lib
@{
*/
/**
* This function resets the decoder. The context must be reset when
* changing streams, or if the following stream parameters change:
* number of subbands, stereo mode, or frequency.
*
* @param context Pointer to the decoder context structure to be reset.
*
* @param enhanced If true, enhanced SBC operation is enabled. If enabled,
* the codec will recognize the alternative syncword for
* decoding an enhanced SBC stream. Enhancements should not
* be enabled unless the stream is known to be generated
* by an enhanced encoder, or there is a small possibility
* for decoding glitches if synchronization were to be lost.
*/
OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride,
OI_BOOL enhanced);
/* BK4BTSTACK_CHANGE START */
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes);
/* BK4BTSTACK_CHANGE END */
/**
* This function restricts the kind of SBC frames that the Decoder will
* process. Its use is optional. If used, it must be called after
* calling OI_CODEC_SBC_DecoderReset(). After it is called, any calls
* to OI_CODEC_SBC_DecodeFrame() with SBC frames that do not conform
* to the Subband and Enhanced SBC setting will be rejected with an
* OI_STATUS_INVALID_PARAMETERS return.
*
* @param context Pointer to the decoder context structure to be limited.
*
* @param enhanced If true, all frames passed to the decoder must be
* Enhanced SBC frames. If false, all frames must be
* standard SBC frames.
*
* @param subbands May be set to SBC_SUBBANDS_4 or SBC_SUBBANDS_8. All
* frames passed to the decoder must be encoded with
* the requested number of subbands.
*
*/
OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 subbands);
/**
* This function sets the decoder parameters for a raw decode where the decoder parameters are not
* available in the sbc data stream. OI_CODEC_SBC_DecoderReset must be called
* prior to calling this function.
*
* @param context Decoder context structure. This must be the context must be
* used each time a frame is decoded.
*
* @param enhanced Set to TRUE to enable Qualcomm proprietary
* quality enhancements.
*
* @param frequency One of SBC_FREQ_16000, SBC_FREQ_32000, SBC_FREQ_44100,
* SBC_FREQ_48000
*
* @param mode One of SBC_MONO, SBC_DUAL_CHANNEL, SBC_STEREO,
* SBC_JOINT_STEREO
*
* @param subbands One of SBC_SUBBANDS_4, SBC_SUBBANDS_8
*
* @param blocks One of SBC_BLOCKS_4, SBC_BLOCKS_8, SBC_BLOCKS_12,
* SBC_BLOCKS_16
*
* @param alloc One of SBC_LOUDNESS, SBC_SNR
*
* @param maxBitpool The maximum bitpool size for this context
*/
OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 frequency,
OI_UINT8 mode,
OI_UINT8 subbands,
OI_UINT8 blocks,
OI_UINT8 alloc,
OI_UINT8 maxBitpool);
/**
* Decode one SBC frame. The frame has no header bytes. The context must have been previously
* initialized by calling OI_CODEC_SBC_DecoderConfigureRaw().
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param bitpool The actual bitpool size for this frame. Must be <= the maxbitpool specified
* in the call to OI_CODEC_SBC_DecoderConfigureRaw(),
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
* @param pcmData Address of an array of OI_INT16 pairs, which will be
* populated with the decoded audio data. This address
* is not updated.
*
* @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it
* should contain the number of bytes available for pcm
* data. On output, it will contain the number of bytes
* written. Note that this differs from the semantics of
* frameBytes.
*/
OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
/**
* Decode one SBC frame.
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
* @param pcmData Address of an array of OI_INT16 pairs, which will be
* populated with the decoded audio data. This address
* is not updated.
*
* @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it
* should contain the number of bytes available for pcm
* data. On output, it will contain the number of bytes
* written. Note that this differs from the semantics of
* frameBytes.
*/
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
/**
* Calculate the number of SBC frames but don't decode. CRC's are not checked,
* but the Sync word is found prior to count calculation.
*
* @param frameData Pointer to the SBC data.
*
* @param frameBytes Number of bytes avaiable in the frameData buffer
*
*/
OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData,
OI_UINT32 frameBytes);
/**
* Analyze an SBC frame but don't do the decode.
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
*/
OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes);
/* Common functions */
/**
Calculate the frame length.
@param frame The frame whose length to calculate
@return the length of an individual encoded frame in
bytes
*/
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame);
/**
* Calculate the maximum bitpool size that fits within a given frame length.
*
* @param frame The frame to calculate the bitpool size for
* @param frameLen The frame length to fit the bitpool to
*
* @return the maximum bitpool that will fit in the specified frame length
*/
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
OI_UINT16 frameLen);
/**
Calculate the bit rate.
@param frame The frame whose bit rate to calculate
@return the approximate bit rate in bits per second,
assuming that stream parameters are constant
*/
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame);
/**
Calculate decoded audio data length for one frame.
@param frame The frame whose audio data length to calculate
@return length of decoded audio data for a
single frame, in bytes
*/
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common);
/**
* Get the codec version text.
*
* @return pointer to text string containing codec version text
*
*/
const OI_CHAR *OI_CODEC_Version(void);
/**
@}
@addtogroup codec_internal
@{
*/
extern const OI_CHAR* const OI_CODEC_SBC_FreqText[];
extern const OI_CHAR* const OI_CODEC_SBC_ModeText[];
extern const OI_CHAR* const OI_CODEC_SBC_SubbandsText[];
extern const OI_CHAR* const OI_CODEC_SBC_BlocksText[];
extern const OI_CHAR* const OI_CODEC_SBC_AllocText[];
/**
@}
@addtogroup codec_lib
@{
*/
#ifdef OI_DEBUG
void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo);
#else
#define OI_CODEC_SBC_DumpConfig(f)
#endif
/**
@}
*/
#ifdef __cplusplus
}
#endif
#endif /* _OI_CODEC_SBC_CORE_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#ifndef _OI_CODEC_SBC_CORE_H
#define _OI_CODEC_SBC_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/**
@file
Declarations of codec functions, data types, and macros.
@ingroup codec_lib
*/
/**
@addtogroup codec_lib
@{
*/
/* Non-BM3 users of of the codec must include oi_codec_sbc_bm3defs.h prior to
* including this file, or else these includes will fail because the BM3 SDK is
* not in the include path */
#ifndef _OI_CODEC_SBC_BM3DEFS_H
#include "oi_stddefs.h"
#include "oi_status.h"
#endif
#include <stdint.h>
#define SBC_MAX_CHANNELS 2
#define SBC_MAX_BANDS 8
#define SBC_MAX_BLOCKS 16
#define SBC_MIN_BITPOOL 2 /**< Minimum size of the bit allocation pool used to encode the stream */
#define SBC_MAX_BITPOOL 250 /**< Maximum size of the bit allocation pool used to encode the stream */
#define SBC_MAX_ONE_CHANNEL_BPS 320000
#define SBC_MAX_TWO_CHANNEL_BPS 512000
#define SBC_WBS_BITRATE 62000
#define SBC_WBS_BITPOOL 27
#define SBC_WBS_NROF_BLOCKS 16
#define SBC_WBS_FRAME_LEN 62
#define SBC_WBS_SAMPLES_PER_FRAME 128
#define SBC_HEADER_LEN 4
#define SBC_MAX_FRAME_LEN (SBC_HEADER_LEN + \
((SBC_MAX_BANDS * SBC_MAX_CHANNELS / 2) + \
((SBC_MAX_BANDS + (SBC_MAX_BLOCKS * SBC_MAX_BITPOOL) + 7)/8)))
#define SBC_MAX_SAMPLES_PER_FRAME (SBC_MAX_BANDS * SBC_MAX_BLOCKS)
#define SBC_MAX_SCALEFACTOR_BYTES ((4*(SBC_MAX_CHANNELS * SBC_MAX_BANDS) + 7)/8)
#define OI_SBC_SYNCWORD 0x9c
#define OI_SBC_ENHANCED_SYNCWORD 0x9d
/**@name Sampling frequencies */
/**@{*/
#define SBC_FREQ_16000 0 /**< The sampling frequency is 16 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_32000 1 /**< The sampling frequency is 32 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_44100 2 /**< The sampling frequency is 44.1 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_FREQ_48000 3 /**< The sampling frequency is 48 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Channel modes */
/**@{*/
#define SBC_MONO 0 /**< The mode of the encoded channel is mono. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_DUAL_CHANNEL 1 /**< The mode of the encoded channel is dual-channel. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_STEREO 2 /**< The mode of the encoded channel is stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_JOINT_STEREO 3 /**< The mode of the encoded channel is joint stereo. One possible value for the @a mode parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Subbands */
/**@{*/
#define SBC_SUBBANDS_4 0 /**< The encoded stream has 4 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure()*/
#define SBC_SUBBANDS_8 1 /**< The encoded stream has 8 subbands. One possible value for the @a subbands parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Block lengths */
/**@{*/
#define SBC_BLOCKS_4 0 /**< A block size of 4 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_8 1 /**< A block size of 8 blocks was used to encode the stream is. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_12 2 /**< A block size of 12 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_BLOCKS_16 3 /**< A block size of 16 blocks was used to encode the stream. One possible value for the @a blocks parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**@name Bit allocation methods */
/**@{*/
#define SBC_LOUDNESS 0 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */
#define SBC_SNR 1 /**< The bit allocation method. One possible value for the @a loudness parameter of OI_CODEC_SBC_EncoderConfigure() */
/**@}*/
/**
@}
@addtogroup codec_internal
@{
*/
typedef OI_INT16 SBC_BUFFER_T;
/** Used internally. */
typedef struct {
OI_UINT16 frequency; /**< The sampling frequency. Input parameter. */
OI_UINT8 freqIndex;
OI_UINT8 nrof_blocks; /**< The block size used to encode the stream. Input parameter. */
OI_UINT8 blocks;
OI_UINT8 nrof_subbands; /**< The number of subbands of the encoded stream. Input parameter. */
OI_UINT8 subbands;
OI_UINT8 mode; /**< The mode of the encoded channel. Input parameter. */
OI_UINT8 nrof_channels; /**< The number of channels of the encoded stream. */
OI_UINT8 alloc; /**< The bit allocation method. Input parameter. */
OI_UINT8 bitpool; /**< Size of the bit allocation pool used to encode the stream. Input parameter. */
OI_UINT8 crc; /**< Parity check byte used for error detection. */
OI_UINT8 join; /**< Whether joint stereo has been used. */
OI_UINT8 enhanced;
OI_UINT8 min_bitpool; /**< This value is only used when encoding. SBC_MAX_BITPOOL if variable
bitpools are disallowed, otherwise the minimum bitpool size that will
be used by the bit allocator. */
OI_UINT8 cachedInfo; /**< Information about the previous frame */
/* BK4BTSTACK_CHANGE START */
OI_UINT8 reserved_for_future_use[2];
OI_UINT8 mSBCEnabled; // default 0
/* BK4BTSTACK_CHANGE END */
} OI_CODEC_SBC_FRAME_INFO;
/** Used internally. */
typedef struct {
const OI_CHAR *codecInfo;
OI_CODEC_SBC_FRAME_INFO frameInfo;
OI_INT8 scale_factor[SBC_MAX_CHANNELS*SBC_MAX_BANDS];
OI_UINT32 frameCount;
OI_INT32 *subdata;
SBC_BUFFER_T *filterBuffer[SBC_MAX_CHANNELS];
OI_INT32 filterBufferLen;
OI_UINT filterBufferOffset;
union {
OI_UINT8 uint8[SBC_MAX_CHANNELS*SBC_MAX_BANDS];
OI_UINT32 uint32[SBC_MAX_CHANNELS*SBC_MAX_BANDS/4];
} bits;
OI_UINT8 maxBitneed; /**< Running maximum bitneed */
OI_BYTE formatByte;
OI_UINT8 pcmStride;
OI_UINT8 maxChannels;
} OI_CODEC_SBC_COMMON_CONTEXT;
/*
* A smaller value reduces RAM usage at the expense of increased CPU usage. Values in the range
* 27..50 are recommended, beyond 50 there is a diminishing return on reduced CPU usage.
*/
#define SBC_CODEC_MIN_FILTER_BUFFERS 16
#define SBC_CODEC_FAST_FILTER_BUFFERS 27
/* Expands to the number of OI_UINT32s needed to ensure enough memory to encode
* or decode streams of numChannels channels, using numBuffers buffers.
* Example:
* OI_UINT32 decoderData[CODEC_DATA_WORDS(SBC_MAX_CHANNELS, SBC_DECODER_FAST_SYNTHESIS_BUFFERS)];
* */
#define CODEC_DATA_WORDS(numChannels, numBuffers) \
((\
(sizeof(OI_INT32) * SBC_MAX_BLOCKS * numChannels * SBC_MAX_BANDS) \
+ (sizeof(SBC_BUFFER_T) * SBC_MAX_CHANNELS * SBC_MAX_BANDS * numBuffers) \
+ (sizeof (OI_UINT32) - 1) \
) / sizeof(OI_UINT32))
/** Opaque parameter to decoding functions; maintains decoder context. */
typedef struct {
OI_CODEC_SBC_COMMON_CONTEXT common;
OI_UINT8 limitFrameFormat; /* Boolean, set by OI_CODEC_SBC_DecoderLimit() */
OI_UINT8 restrictSubbands;
OI_UINT8 enhancedEnabled;
OI_UINT8 bufferedBlocks;
} OI_CODEC_SBC_DECODER_CONTEXT;
typedef struct {
OI_UINT32 data[CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)];
} OI_CODEC_SBC_CODEC_DATA_MONO;
typedef struct {
OI_UINT32 data[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
} OI_CODEC_SBC_CODEC_DATA_STEREO;
/**
@}
@addtogroup codec_lib
@{
*/
/**
* This function resets the decoder. The context must be reset when
* changing streams, or if the following stream parameters change:
* number of subbands, stereo mode, or frequency.
*
* @param context Pointer to the decoder context structure to be reset.
*
* @param enhanced If true, enhanced SBC operation is enabled. If enabled,
* the codec will recognize the alternative syncword for
* decoding an enhanced SBC stream. Enhancements should not
* be enabled unless the stream is known to be generated
* by an enhanced encoder, or there is a small possibility
* for decoding glitches if synchronization were to be lost.
*/
OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride,
OI_BOOL enhanced);
/* BK4BTSTACK_CHANGE START */
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes);
/* BK4BTSTACK_CHANGE END */
/**
* This function restricts the kind of SBC frames that the Decoder will
* process. Its use is optional. If used, it must be called after
* calling OI_CODEC_SBC_DecoderReset(). After it is called, any calls
* to OI_CODEC_SBC_DecodeFrame() with SBC frames that do not conform
* to the Subband and Enhanced SBC setting will be rejected with an
* OI_STATUS_INVALID_PARAMETERS return.
*
* @param context Pointer to the decoder context structure to be limited.
*
* @param enhanced If true, all frames passed to the decoder must be
* Enhanced SBC frames. If false, all frames must be
* standard SBC frames.
*
* @param subbands May be set to SBC_SUBBANDS_4 or SBC_SUBBANDS_8. All
* frames passed to the decoder must be encoded with
* the requested number of subbands.
*
*/
OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 subbands);
/**
* This function sets the decoder parameters for a raw decode where the decoder parameters are not
* available in the sbc data stream. OI_CODEC_SBC_DecoderReset must be called
* prior to calling this function.
*
* @param context Decoder context structure. This must be the context must be
* used each time a frame is decoded.
*
* @param enhanced Set to TRUE to enable Qualcomm proprietary
* quality enhancements.
*
* @param frequency One of SBC_FREQ_16000, SBC_FREQ_32000, SBC_FREQ_44100,
* SBC_FREQ_48000
*
* @param mode One of SBC_MONO, SBC_DUAL_CHANNEL, SBC_STEREO,
* SBC_JOINT_STEREO
*
* @param subbands One of SBC_SUBBANDS_4, SBC_SUBBANDS_8
*
* @param blocks One of SBC_BLOCKS_4, SBC_BLOCKS_8, SBC_BLOCKS_12,
* SBC_BLOCKS_16
*
* @param alloc One of SBC_LOUDNESS, SBC_SNR
*
* @param maxBitpool The maximum bitpool size for this context
*/
OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 frequency,
OI_UINT8 mode,
OI_UINT8 subbands,
OI_UINT8 blocks,
OI_UINT8 alloc,
OI_UINT8 maxBitpool);
/**
* Decode one SBC frame. The frame has no header bytes. The context must have been previously
* initialized by calling OI_CODEC_SBC_DecoderConfigureRaw().
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param bitpool The actual bitpool size for this frame. Must be <= the maxbitpool specified
* in the call to OI_CODEC_SBC_DecoderConfigureRaw(),
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
* @param pcmData Address of an array of OI_INT16 pairs, which will be
* populated with the decoded audio data. This address
* is not updated.
*
* @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it
* should contain the number of bytes available for pcm
* data. On output, it will contain the number of bytes
* written. Note that this differs from the semantics of
* frameBytes.
*/
OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
/**
* Decode one SBC frame.
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
* @param pcmData Address of an array of OI_INT16 pairs, which will be
* populated with the decoded audio data. This address
* is not updated.
*
* @param pcmBytes Pointer to a UINT32 in/out parameter. On input, it
* should contain the number of bytes available for pcm
* data. On output, it will contain the number of bytes
* written. Note that this differs from the semantics of
* frameBytes.
*/
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
/**
* Calculate the number of SBC frames but don't decode. CRC's are not checked,
* but the Sync word is found prior to count calculation.
*
* @param frameData Pointer to the SBC data.
*
* @param frameBytes Number of bytes avaiable in the frameData buffer
*
*/
OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData,
OI_UINT32 frameBytes);
/**
* Analyze an SBC frame but don't do the decode.
*
* @param context Pointer to a decoder context structure. The same context
* must be used each time when decoding from the same stream.
*
* @param frameData Address of a pointer to the SBC data to decode. This
* value will be updated to point to the next frame after
* successful decoding.
*
* @param frameBytes Pointer to a UINT32 containing the number of available
* bytes of frame data. This value will be updated to reflect
* the number of bytes remaining after a decoding operation.
*
*/
OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes);
/* Common functions */
/**
Calculate the frame length.
@param frame The frame whose length to calculate
@return the length of an individual encoded frame in
bytes
*/
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame);
/**
* Calculate the maximum bitpool size that fits within a given frame length.
*
* @param frame The frame to calculate the bitpool size for
* @param frameLen The frame length to fit the bitpool to
*
* @return the maximum bitpool that will fit in the specified frame length
*/
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
OI_UINT16 frameLen);
/**
Calculate the bit rate.
@param frame The frame whose bit rate to calculate
@return the approximate bit rate in bits per second,
assuming that stream parameters are constant
*/
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame);
/**
Calculate decoded audio data length for one frame.
@param frame The frame whose audio data length to calculate
@return length of decoded audio data for a
single frame, in bytes
*/
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common);
/**
* Get the codec version text.
*
* @return pointer to text string containing codec version text
*
*/
const OI_CHAR *OI_CODEC_Version(void);
/**
@}
@addtogroup codec_internal
@{
*/
extern const OI_CHAR* const OI_CODEC_SBC_FreqText[];
extern const OI_CHAR* const OI_CODEC_SBC_ModeText[];
extern const OI_CHAR* const OI_CODEC_SBC_SubbandsText[];
extern const OI_CHAR* const OI_CODEC_SBC_BlocksText[];
extern const OI_CHAR* const OI_CODEC_SBC_AllocText[];
/**
@}
@addtogroup codec_lib
@{
*/
#ifdef OI_DEBUG
void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo);
#else
#define OI_CODEC_SBC_DumpConfig(f)
#endif
/**
@}
*/
#ifdef __cplusplus
}
#endif
#endif /* _OI_CODEC_SBC_CORE_H */
@@ -1,237 +1,237 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_CODEC_SBC_PRIVATE_H
#define _OI_CODEC_SBC_PRIVATE_H
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Function prototypes and macro definitions used internally by the codec.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#ifdef USE_RESTRICT_KEYWORD
#define RESTRICT restrict
#else
#define RESTRICT
#endif
#ifdef CODEC_DEBUG
#include <stdio.h>
#define ERROR(x) do { printf x; printf("\n"); } while (0)
#else
#define ERROR(x)
#endif
#ifdef TRACE_EXECUTION
#include <stdio.h>
#define TRACE(x) do { printf x; printf("\n"); } while (0)
#else
#define TRACE(x)
#endif
#ifndef PRIVATE
#define PRIVATE
#endif
#ifndef INLINE
#define INLINE
#endif
#include "oi_assert.h"
#include "oi_codec_sbc.h"
/* BK4BTSTACK_CHANGE START */
#ifndef OI_mSBC_SYNCWORD
#define OI_mSBC_SYNCWORD 0xad
#endif
/* BK4BTSTACK_CHANGE END */
#ifndef OI_SBC_SYNCWORD
#define OI_SBC_SYNCWORD 0x9c
#endif
#ifndef DIVIDE
#define DIVIDE(a, b) ((a) / (b))
#endif
typedef union {
OI_UINT8 uint8[SBC_MAX_BANDS];
OI_UINT32 uint32[SBC_MAX_BANDS / 4];
} BITNEED_UNION1;
typedef union {
OI_UINT8 uint8[2 * SBC_MAX_BANDS];
OI_UINT32 uint32[2 * SBC_MAX_BANDS / 4];
} BITNEED_UNION2;
static const OI_UINT16 freq_values[] = { 16000, 32000, 44100, 48000 };
static const OI_UINT8 block_values[] = { 4, 8, 12, 16 };
static const OI_UINT8 channel_values[] = { 1, 2, 2, 2 };
static const OI_UINT8 band_values[] = { 4, 8 };
#define TEST_MODE_SENTINEL "OINA"
#define TEST_MODE_SENTINEL_LENGTH 4
/** Used internally. */
typedef struct {
union {
const OI_UINT8 *r;
OI_UINT8 *w;
} ptr;
OI_UINT32 value;
OI_UINT bitPtr;
} OI_BITSTREAM;
#define VALID_INT16(x) (((x) >= OI_INT16_MIN) && ((x) <= OI_INT16_MAX))
#define VALID_INT32(x) (((x) >= OI_INT32_MIN) && ((x) <= OI_INT32_MAX))
#define DCTII_8_SHIFT_IN 0
#define DCTII_8_SHIFT_OUT 16-DCTII_8_SHIFT_IN
#define DCTII_8_SHIFT_0 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_1 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_2 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_3 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_4 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_5 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_6 (DCTII_8_SHIFT_OUT-1)
#define DCTII_8_SHIFT_7 (DCTII_8_SHIFT_OUT-2)
#define DCT_SHIFT 15
#define DCTIII_4_SHIFT_IN 2
#define DCTIII_4_SHIFT_OUT 15
#define DCTIII_8_SHIFT_IN 3
#define DCTIII_8_SHIFT_OUT 14
OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT8 *bitneeds,
OI_UINT ch,
OI_UINT *preferredBitpool);
void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common,
BITNEED_UNION1 *bitneeds,
OI_UINT ch,
OI_UINT bitcount);
OI_INT adjustToFitBitpool(const OI_UINT bitpool,
OI_UINT32 *bitneeds,
const OI_UINT subbands,
OI_UINT bitcount,
OI_UINT *excess);
INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest,
OI_INT bits,
OI_INT excess);
INLINE OI_INT allocExcessBits(OI_UINT8 *dest,
OI_INT excess);
PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame);
void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common);
typedef void (*BIT_ALLOC)(OI_CODEC_SBC_COMMON_CONTEXT *common);
PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_BYTE maxChannels,
OI_BYTE pcmStride,
OI_BOOL enhanced);
INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_);
PRIVATE OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *frame);
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data);
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum_mSBC(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data);
/* Transform functions */
PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount);
PRIVATE void cosineModulateSynth4(SBC_BUFFER_T * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buffer[80], OI_UINT strideShift);
INLINE void dct3_4(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void analyze4_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 40],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[4]);
INLINE void dct3_8(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void analyze8_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 80],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[8]);
#ifdef SBC_ENHANCED
PRIVATE void analyze8_enhanced_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 112],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[8]);
#endif
/* Decoder functions */
INLINE void OI_SBC_ReadHeader_mSBC(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data);
INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data);
PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *b, OI_BITSTREAM *bs);
PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *ob);
PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT start_block, OI_UINT nrof_blocks);
INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits);
PRIVATE OI_BOOL OI_SBC_ExamineCommandPacket(OI_CODEC_SBC_DECODER_CONTEXT *context, const OI_BYTE *data, OI_UINT32 len);
PRIVATE void OI_SBC_GenerateTestSignal(OI_INT16 pcmData[][2], OI_UINT32 sampleCount);
PRIVATE void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT32 *codecDataAligned,
OI_UINT32 codecDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride);
/**
@}
*/
#endif /* _OI_CODEC_SBC_PRIVATE_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_CODEC_SBC_PRIVATE_H
#define _OI_CODEC_SBC_PRIVATE_H
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Function prototypes and macro definitions used internally by the codec.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#ifdef USE_RESTRICT_KEYWORD
#define RESTRICT restrict
#else
#define RESTRICT
#endif
#ifdef CODEC_DEBUG
#include <stdio.h>
#define ERROR(x) do { printf x; printf("\n"); } while (0)
#else
#define ERROR(x)
#endif
#ifdef TRACE_EXECUTION
#include <stdio.h>
#define TRACE(x) do { printf x; printf("\n"); } while (0)
#else
#define TRACE(x)
#endif
#ifndef PRIVATE
#define PRIVATE
#endif
#ifndef INLINE
#define INLINE
#endif
#include "oi_assert.h"
#include "oi_codec_sbc.h"
/* BK4BTSTACK_CHANGE START */
#ifndef OI_mSBC_SYNCWORD
#define OI_mSBC_SYNCWORD 0xad
#endif
/* BK4BTSTACK_CHANGE END */
#ifndef OI_SBC_SYNCWORD
#define OI_SBC_SYNCWORD 0x9c
#endif
#ifndef DIVIDE
#define DIVIDE(a, b) ((a) / (b))
#endif
typedef union {
OI_UINT8 uint8[SBC_MAX_BANDS];
OI_UINT32 uint32[SBC_MAX_BANDS / 4];
} BITNEED_UNION1;
typedef union {
OI_UINT8 uint8[2 * SBC_MAX_BANDS];
OI_UINT32 uint32[2 * SBC_MAX_BANDS / 4];
} BITNEED_UNION2;
static const OI_UINT16 freq_values[] = { 16000, 32000, 44100, 48000 };
static const OI_UINT8 block_values[] = { 4, 8, 12, 16 };
static const OI_UINT8 channel_values[] = { 1, 2, 2, 2 };
static const OI_UINT8 band_values[] = { 4, 8 };
#define TEST_MODE_SENTINEL "OINA"
#define TEST_MODE_SENTINEL_LENGTH 4
/** Used internally. */
typedef struct {
union {
const OI_UINT8 *r;
OI_UINT8 *w;
} ptr;
OI_UINT32 value;
OI_UINT bitPtr;
} OI_BITSTREAM;
#define VALID_INT16(x) (((x) >= OI_INT16_MIN) && ((x) <= OI_INT16_MAX))
#define VALID_INT32(x) (((x) >= OI_INT32_MIN) && ((x) <= OI_INT32_MAX))
#define DCTII_8_SHIFT_IN 0
#define DCTII_8_SHIFT_OUT 16-DCTII_8_SHIFT_IN
#define DCTII_8_SHIFT_0 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_1 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_2 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_3 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_4 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_5 (DCTII_8_SHIFT_OUT)
#define DCTII_8_SHIFT_6 (DCTII_8_SHIFT_OUT-1)
#define DCTII_8_SHIFT_7 (DCTII_8_SHIFT_OUT-2)
#define DCT_SHIFT 15
#define DCTIII_4_SHIFT_IN 2
#define DCTIII_4_SHIFT_OUT 15
#define DCTIII_8_SHIFT_IN 3
#define DCTIII_8_SHIFT_OUT 14
OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT8 *bitneeds,
OI_UINT ch,
OI_UINT *preferredBitpool);
void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common,
BITNEED_UNION1 *bitneeds,
OI_UINT ch,
OI_UINT bitcount);
OI_INT adjustToFitBitpool(const OI_UINT bitpool,
OI_UINT32 *bitneeds,
const OI_UINT subbands,
OI_UINT bitcount,
OI_UINT *excess);
INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest,
OI_INT bits,
OI_INT excess);
INLINE OI_INT allocExcessBits(OI_UINT8 *dest,
OI_INT excess);
PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame);
void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common);
typedef void (*BIT_ALLOC)(OI_CODEC_SBC_COMMON_CONTEXT *common);
PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes);
INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_BYTE maxChannels,
OI_BYTE pcmStride,
OI_BOOL enhanced);
INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_);
PRIVATE OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *frame);
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data);
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum_mSBC(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data);
/* Transform functions */
PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount);
PRIVATE void cosineModulateSynth4(SBC_BUFFER_T * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buffer[80], OI_UINT strideShift);
INLINE void dct3_4(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void analyze4_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 40],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[4]);
INLINE void dct3_8(OI_INT32 * RESTRICT out, OI_INT32 const * RESTRICT in);
PRIVATE void analyze8_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 80],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[8]);
#ifdef SBC_ENHANCED
PRIVATE void analyze8_enhanced_generated(SBC_BUFFER_T analysisBuffer[RESTRICT 112],
OI_INT16 *pcm,
OI_UINT strideShift,
OI_INT32 subband[8]);
#endif
/* Decoder functions */
INLINE void OI_SBC_ReadHeader_mSBC(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data);
INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data);
PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *b, OI_BITSTREAM *bs);
PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *ob);
PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *common, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_SynthFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_INT16 *pcm, OI_UINT start_block, OI_UINT nrof_blocks);
INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits);
PRIVATE OI_BOOL OI_SBC_ExamineCommandPacket(OI_CODEC_SBC_DECODER_CONTEXT *context, const OI_BYTE *data, OI_UINT32 len);
PRIVATE void OI_SBC_GenerateTestSignal(OI_INT16 pcmData[][2], OI_UINT32 sampleCount);
PRIVATE void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame);
PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT32 *codecDataAligned,
OI_UINT32 codecDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride);
/**
@}
*/
#endif /* _OI_CODEC_SBC_PRIVATE_H */
+43 -43
View File
@@ -1,43 +1,43 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_COMMON_H
#define _OI_COMMON_H
/**
* @file
*
* This file is used to group commonly used BLUEmagic 3.0 software
* header files.
*
* This file should be included in application source code along with the header
* files for the specific modules of the protocol stack being used.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_bt_spec.h"
#include "oi_stddefs.h"
#include "oi_status.h"
#include "oi_time.h"
#include "oi_osinterface.h"
/*****************************************************************************/
#endif /* _OI_COMMON_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_COMMON_H
#define _OI_COMMON_H
/**
* @file
*
* This file is used to group commonly used BLUEmagic 3.0 software
* header files.
*
* This file should be included in application source code along with the header
* files for the specific modules of the protocol stack being used.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_bt_spec.h"
#include "oi_stddefs.h"
#include "oi_status.h"
#include "oi_time.h"
#include "oi_osinterface.h"
/*****************************************************************************/
#endif /* _OI_COMMON_H */
File diff suppressed because it is too large Load Diff
+171 -171
View File
@@ -1,171 +1,171 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_MODULES_H
#define _OI_MODULES_H
/**
* @file
*
* Enumeration type defining the inidivual stack components.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* This enumeration lists constants for referencing the components of
* the BLUEmagic 3.0 protocol stack, profiles, and other functionalities.
*
* In order to distinguish types of modules, items are grouped with markers to
* delineate start and end of the groups
*
* The module type is used for various purposes:
* identification in debug print statements
* access to initialization flags
* access to the configuration table
*/
typedef enum {
/* profiles and protocols --> Updates to oi_debug.c and oi_config_table.c */
/* XX --> Keep Enum values up-to-date! */
OI_MODULE_AT, /**< 00 AT command processing */
OI_MODULE_A2DP, /**< 01 Advanced Audio Distribution Profile */
OI_MODULE_AVCTP, /**< 02 Audio-Visual Control Transport Profile */
OI_MODULE_AVDTP, /**< 03 Audio-Visual Distribution Protocol */
OI_MODULE_AVRCP, /**< 04 Audio-Visual Remote Control Profile */
OI_MODULE_BIP_CLI, /**< 05 Basic Imaging Profile protocol client */
OI_MODULE_BIP_SRV, /**< 06 Basic Imaging Profile protocol server */
OI_MODULE_BNEP, /**< 07 Bluetooth Network Encapsulation Protocol */
OI_MODULE_BPP_SENDER, /**< 08 Basic Printing Profile */
OI_MODULE_BPP_PRINTER, /**< 09 Basic Printing Profile */
OI_MODULE_CTP, /**< 10 Cordless Telephony Profile */
OI_MODULE_DUN, /**< 11 Dial-Up Networking Profile */
OI_MODULE_FAX, /**< 12 Fax Profile */
OI_MODULE_FTP_CLI, /**< 13 File Transfer Profile protocol client */
OI_MODULE_FTP_SRV, /**< 14 File Transfer Profile protocol server */
OI_MODULE_HANDSFREE, /**< 15 Hands-Free Profile */
OI_MODULE_HANDSFREE_AG, /**< 16 Hands-Free Profile */
OI_MODULE_HCRP_CLI, /**< 17 Hardcopy Cable Replacement Profile */
OI_MODULE_HCRP_SRV, /**< 18 Hardcopy Cable Replacement Profile */
OI_MODULE_HEADSET, /**< 19 Headset Profile */
OI_MODULE_HEADSET_AG, /**< 20 Headset Profile */
OI_MODULE_HID, /**< 21 Human Interface Device profile */
OI_MODULE_INTERCOM, /**< 22 Intercom Profile */
OI_MODULE_OBEX_CLI, /**< 23 OBEX protocol client, Generic Object Exchange Profile */
OI_MODULE_OBEX_SRV, /**< 24 OBEX protocol server, Generic Object Exchange Profile */
OI_MODULE_OPP_CLI, /**< 25 Object Push Profile protocol client */
OI_MODULE_OPP_SRV, /**< 26 Object Push Profile protocol server */
OI_MODULE_PAN, /**< 27 PAN profile */
OI_MODULE_PBAP_CLI, /**< 28 Phonebook Access Profile client */
OI_MODULE_PBAP_SRV, /**< 29 Phonebook Access Profile server */
OI_MODULE_SAP_CLI, /**< 30 SIM Access Profile */
OI_MODULE_SAP_SRV, /**< 31 SIM Access Profile */
OI_MODULE_SPP, /**< 32 Serial Port Profile */
OI_MODULE_SYNC_CLI, /**< 33 Synchronization Profile */
OI_MODULE_SYNC_SRV, /**< 34 Synchronization Profile */
OI_MODULE_SYNC_CMD_CLI, /**< 35 Synchronization Profile */
OI_MODULE_SYNC_CMD_SRV, /**< 36 Synchronization Profile */
OI_MODULE_SYNCML, /**< 37 SyncML Profile */
OI_MODULE_TCS, /**< 38 TCS Binary */
OI_MODULE_VDP, /**< 39 Video Distribution Profile */
/* corestack components --> Updates to oi_debug.c and oi_config_table.c */
OI_MODULE_COMMON_CONFIG, /**< 40 Common configuration, module has no meaning other than for config struct */
OI_MODULE_CMDCHAIN, /**< 41 Command chaining utility */
OI_MODULE_DISPATCH, /**< 42 Dispatcher */
OI_MODULE_DATAELEM, /**< 43 Data Elements, marshaller */
OI_MODULE_DEVMGR, /**< 44 Device Manager */
OI_MODULE_DEVMGR_MODES, /**< 45 Device Manager connectability/discoverability modes */
OI_MODULE_HCI, /**< 46 Host Controller Interface command layer */
OI_MODULE_L2CAP, /**< 47 L2CAP */
OI_MODULE_MEMMGR, /**< 48 modules that do memory management */
OI_MODULE_POLICYMGR, /**< 49 Policy Manager */
OI_MODULE_RFCOMM, /**< 50 RFCOMM */
OI_MODULE_RFCOMM_SD, /**< 51 RFCOMM Service discovery */
OI_MODULE_SDP_CLI, /**< 52 Service Discovery Protocol client */
OI_MODULE_SDP_SRV, /**< 53 Service Discovery Protocol server */
OI_MODULE_SDPDB, /**< 54 Service Discovery Protocol database */
OI_MODULE_SECMGR, /**< 55 Security Manager */
OI_MODULE_SNIFFLOG, /**< 56 sniff log */
OI_MODULE_SUPPORT, /**< 57 support functions, including CThru Dispatcher, time functions, and stack initialization */
OI_MODULE_TRANSPORT, /**< 58 transport layer between HCI command layer and driver */
OI_MODULE_TEST, /**< 59 used to debug output from internal test programs */
OI_MODULE_XML, /**< 60 XML/CSS parser */
OI_MODULE_DI, /**< 61 Device Identification Profile */
// bhapi components --> Updates to oi_debug.c
OI_MODULE_BHAPI, /**< 62 BLUEmagic Host API generic */
OI_MODULE_BHCLI, /**< 63 BLUEmagic Host API client side */
OI_MODULE_BHSRV, /**< 64 BLUEmagic Host API server side */
OI_MODULE_MSGQ, /**< 65 module that handles message queuing */
OI_MODULE_BHAPI_TRANSPORT, /**< 66 module that handles message queuing */
OI_MODULE_BLST_SRV, /**< 67 module that provides server side BHAPI Lightweight Serial Transport */
OI_MODULE_BLST_CLI, /**< 68 module that provides client side BHAPI Lightweight Serial Transport */
// OEM files --> Updates to oi_debug.c
OI_MODULE_OEM, /**< 69 Application Memory allocation */
// Application glue --> Updates to oi_debug.c
OI_MODULE_APP, /**< 70 Application Memory allocation */
/* various pieces of code depend on these last 2 elements occuring in a specific order:
OI_MODULE_ALL must be the 2nd to last element
OI_MODULE_UNKNOWN must be the last element
*/
OI_MODULE_ALL, /**< 71 special value identifying all modules - used for control of debug print statements */
OI_MODULE_UNKNOWN /**< 72 special value - used for debug print statements */
} OI_MODULE;
/**
* This constant is the number of actual modules in the list. ALL and UNKNOWN are
* special values that are not actually modules.
* Used for debug print and memmgr profiling
*/
#define OI_NUM_MODULES OI_MODULE_ALL
/**
* This constant is the number of profile and core components. It is used to size
* the initialization and configuration tables.
*/
#define OI_NUM_STACK_MODULES OI_MODULE_BHAPI
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_MODULES_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_MODULES_H
#define _OI_MODULES_H
/**
* @file
*
* Enumeration type defining the inidivual stack components.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* This enumeration lists constants for referencing the components of
* the BLUEmagic 3.0 protocol stack, profiles, and other functionalities.
*
* In order to distinguish types of modules, items are grouped with markers to
* delineate start and end of the groups
*
* The module type is used for various purposes:
* identification in debug print statements
* access to initialization flags
* access to the configuration table
*/
typedef enum {
/* profiles and protocols --> Updates to oi_debug.c and oi_config_table.c */
/* XX --> Keep Enum values up-to-date! */
OI_MODULE_AT, /**< 00 AT command processing */
OI_MODULE_A2DP, /**< 01 Advanced Audio Distribution Profile */
OI_MODULE_AVCTP, /**< 02 Audio-Visual Control Transport Profile */
OI_MODULE_AVDTP, /**< 03 Audio-Visual Distribution Protocol */
OI_MODULE_AVRCP, /**< 04 Audio-Visual Remote Control Profile */
OI_MODULE_BIP_CLI, /**< 05 Basic Imaging Profile protocol client */
OI_MODULE_BIP_SRV, /**< 06 Basic Imaging Profile protocol server */
OI_MODULE_BNEP, /**< 07 Bluetooth Network Encapsulation Protocol */
OI_MODULE_BPP_SENDER, /**< 08 Basic Printing Profile */
OI_MODULE_BPP_PRINTER, /**< 09 Basic Printing Profile */
OI_MODULE_CTP, /**< 10 Cordless Telephony Profile */
OI_MODULE_DUN, /**< 11 Dial-Up Networking Profile */
OI_MODULE_FAX, /**< 12 Fax Profile */
OI_MODULE_FTP_CLI, /**< 13 File Transfer Profile protocol client */
OI_MODULE_FTP_SRV, /**< 14 File Transfer Profile protocol server */
OI_MODULE_HANDSFREE, /**< 15 Hands-Free Profile */
OI_MODULE_HANDSFREE_AG, /**< 16 Hands-Free Profile */
OI_MODULE_HCRP_CLI, /**< 17 Hardcopy Cable Replacement Profile */
OI_MODULE_HCRP_SRV, /**< 18 Hardcopy Cable Replacement Profile */
OI_MODULE_HEADSET, /**< 19 Headset Profile */
OI_MODULE_HEADSET_AG, /**< 20 Headset Profile */
OI_MODULE_HID, /**< 21 Human Interface Device profile */
OI_MODULE_INTERCOM, /**< 22 Intercom Profile */
OI_MODULE_OBEX_CLI, /**< 23 OBEX protocol client, Generic Object Exchange Profile */
OI_MODULE_OBEX_SRV, /**< 24 OBEX protocol server, Generic Object Exchange Profile */
OI_MODULE_OPP_CLI, /**< 25 Object Push Profile protocol client */
OI_MODULE_OPP_SRV, /**< 26 Object Push Profile protocol server */
OI_MODULE_PAN, /**< 27 PAN profile */
OI_MODULE_PBAP_CLI, /**< 28 Phonebook Access Profile client */
OI_MODULE_PBAP_SRV, /**< 29 Phonebook Access Profile server */
OI_MODULE_SAP_CLI, /**< 30 SIM Access Profile */
OI_MODULE_SAP_SRV, /**< 31 SIM Access Profile */
OI_MODULE_SPP, /**< 32 Serial Port Profile */
OI_MODULE_SYNC_CLI, /**< 33 Synchronization Profile */
OI_MODULE_SYNC_SRV, /**< 34 Synchronization Profile */
OI_MODULE_SYNC_CMD_CLI, /**< 35 Synchronization Profile */
OI_MODULE_SYNC_CMD_SRV, /**< 36 Synchronization Profile */
OI_MODULE_SYNCML, /**< 37 SyncML Profile */
OI_MODULE_TCS, /**< 38 TCS Binary */
OI_MODULE_VDP, /**< 39 Video Distribution Profile */
/* corestack components --> Updates to oi_debug.c and oi_config_table.c */
OI_MODULE_COMMON_CONFIG, /**< 40 Common configuration, module has no meaning other than for config struct */
OI_MODULE_CMDCHAIN, /**< 41 Command chaining utility */
OI_MODULE_DISPATCH, /**< 42 Dispatcher */
OI_MODULE_DATAELEM, /**< 43 Data Elements, marshaller */
OI_MODULE_DEVMGR, /**< 44 Device Manager */
OI_MODULE_DEVMGR_MODES, /**< 45 Device Manager connectability/discoverability modes */
OI_MODULE_HCI, /**< 46 Host Controller Interface command layer */
OI_MODULE_L2CAP, /**< 47 L2CAP */
OI_MODULE_MEMMGR, /**< 48 modules that do memory management */
OI_MODULE_POLICYMGR, /**< 49 Policy Manager */
OI_MODULE_RFCOMM, /**< 50 RFCOMM */
OI_MODULE_RFCOMM_SD, /**< 51 RFCOMM Service discovery */
OI_MODULE_SDP_CLI, /**< 52 Service Discovery Protocol client */
OI_MODULE_SDP_SRV, /**< 53 Service Discovery Protocol server */
OI_MODULE_SDPDB, /**< 54 Service Discovery Protocol database */
OI_MODULE_SECMGR, /**< 55 Security Manager */
OI_MODULE_SNIFFLOG, /**< 56 sniff log */
OI_MODULE_SUPPORT, /**< 57 support functions, including CThru Dispatcher, time functions, and stack initialization */
OI_MODULE_TRANSPORT, /**< 58 transport layer between HCI command layer and driver */
OI_MODULE_TEST, /**< 59 used to debug output from internal test programs */
OI_MODULE_XML, /**< 60 XML/CSS parser */
OI_MODULE_DI, /**< 61 Device Identification Profile */
// bhapi components --> Updates to oi_debug.c
OI_MODULE_BHAPI, /**< 62 BLUEmagic Host API generic */
OI_MODULE_BHCLI, /**< 63 BLUEmagic Host API client side */
OI_MODULE_BHSRV, /**< 64 BLUEmagic Host API server side */
OI_MODULE_MSGQ, /**< 65 module that handles message queuing */
OI_MODULE_BHAPI_TRANSPORT, /**< 66 module that handles message queuing */
OI_MODULE_BLST_SRV, /**< 67 module that provides server side BHAPI Lightweight Serial Transport */
OI_MODULE_BLST_CLI, /**< 68 module that provides client side BHAPI Lightweight Serial Transport */
// OEM files --> Updates to oi_debug.c
OI_MODULE_OEM, /**< 69 Application Memory allocation */
// Application glue --> Updates to oi_debug.c
OI_MODULE_APP, /**< 70 Application Memory allocation */
/* various pieces of code depend on these last 2 elements occuring in a specific order:
OI_MODULE_ALL must be the 2nd to last element
OI_MODULE_UNKNOWN must be the last element
*/
OI_MODULE_ALL, /**< 71 special value identifying all modules - used for control of debug print statements */
OI_MODULE_UNKNOWN /**< 72 special value - used for debug print statements */
} OI_MODULE;
/**
* This constant is the number of actual modules in the list. ALL and UNKNOWN are
* special values that are not actually modules.
* Used for debug print and memmgr profiling
*/
#define OI_NUM_MODULES OI_MODULE_ALL
/**
* This constant is the number of profile and core components. It is used to size
* the initialization and configuration tables.
*/
#define OI_NUM_STACK_MODULES OI_MODULE_BHAPI
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_MODULES_H */
+197 -197
View File
@@ -1,197 +1,197 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_OSINTERFACE_H
#define _OI_OSINTERFACE_H
/**
@file
* This file provides the platform-independent interface for functions for which
* implementation is platform-specific.
*
* The functions in this header file define the operating system or hardware
* services needed by the BLUEmagic 3.0 protocol stack. The
* actual implementation of these services is platform-dependent.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
#include "oi_time.h"
#include "oi_status.h"
#include "oi_modules.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Terminates execution.
*
* @param reason Reason for termination
*/
void OI_FatalError(OI_STATUS reason);
/**
* This function logs an error.
*
* When built for release mode, BLUEmagic 3 errors are logged to
* this function. (in debug mode, errors are logged via
* OI_Print()).
*
* @param module Module in which the error was detected (see
* oi_modules.h)
* @param lineno Line number of the C file OI_SLOG_ERROR called
* @param status Status code associated with the error event
*/
void OI_LogError(OI_MODULE module, OI_INT lineno, OI_STATUS status);
/**
* This function initializes the debug code handling.
*
* When built for debug mode, this function performs platform
* dependent initialization to handle message codes passed in
* via OI_SetMsgCode().
*/
void OI_InitDebugCodeHandler(void);
/**
* This function reads the time from the real time clock.
*
* All timing in BM3 is relative, typically a granularity
* of 5 or 10 msecs is adequate.
*
* @param[out] now Pointer to the buffer to which the current
* time will be returned
*/
void OI_Time_Now(OI_TIME *now);
/**
* This function causes the current thread to sleep for the
* specified amount of time. This function must be called
* without the stack access token.
*
* @note BM3 corestack and profiles never suspend and never call
* OI_Sleep. The use of OI_Sleep is limited to applications and
* platform-specific code.
*
* If your port and applications never use OI_Sleep, this function can be left unimplemented.
*
* @param milliseconds Number of milliseconds to sleep
*/
void OI_Sleep(OI_UINT32 milliseconds);
/**
* Defines for message type codes.
*/
#define OI_MSG_CODE_APPLICATION 0 /**< Application output */
#define OI_MSG_CODE_ERROR 1 /**< Error message output */
#define OI_MSG_CODE_WARNING 2 /**< Warning message output */
#define OI_MSG_CODE_TRACE 3 /**< User API function trace output */
#define OI_MSG_CODE_PRINT1 4 /**< Catagory 1 debug print output */
#define OI_MSG_CODE_PRINT2 5 /**< Catagory 2 debug print output */
#define OI_MSG_CODE_HEADER 6 /**< Error/Debug output header */
/**
* This function is used to indicate the type of text being output with
* OI_Print(). For the Linux and Win32 platforms, it will set
* the color of the text. Other possible uses could be to insert
* HTML style tags, add some other message type indication, or
* be completely ignored altogether.
*
* @param code OI_MSG_CODE_* indicating setting the message type.
*/
void OI_SetMsgCode(OI_UINT8 code);
/**
* All output from OI_Printf() and all debug output is sent to OI_Print.
* Typically, if the platform has a console, OI_Print() is sent to stdout.
* Embedded platforms typically send OI_Print() output to a serial port.
*
* @param str String to print
*/
void OI_Print(OI_CHAR const *str);
/**
* In cases where OI_Print() is sending output to a logfile in addition to console,
* it is desirable to also put console input into the logfile.
* This function can be called by the console input process.
*
* @note This is an optional API which is strictly
* between the platform-specific stack_console and osinterface
* modules. This API need only be implemented on those
* platforms where is serves a useful purpose, e.g., win32.
*
* @param str Console input string
*/
void OI_Print_ConsoleInput(OI_CHAR const *str);
/**
* This function computes the CRC16 of the program image.
*/
OI_UINT16 OI_ProgramImageCRC16(void);
/**
* Writes an integer to stdout in hex. This macro is intended
* for selective use when debugging in small memory
* configurations or other times when it is not possible to use
* OI_DBGPRINT.
*
* @param n the integer to print
*/
#define OI_Print_Int(n) \
{ \
static const OI_CHAR _digits[] = "0123456789ABCDEF"; \
OI_CHAR _buf[9]; \
OI_CHAR *_str = &_buf[8]; \
OI_UINT32 _i = n; \
*_str = 0; \
do { *(--_str) = _digits[(_i & 0xF)]; _i >>= 4; } while (_i); \
OI_Print(_str); \
}
/**
* Application Dynamic Memory allocation.
*
* These APIs are provided for application use on those
* platforms which have no dynamic memory support. Memory is
* allocated from the pool-based heap managed by the stack's
* internal memory manager.
*/
void *OI_APP_Malloc(OI_INT32 size);
void OI_APP_Free(void *ptr);
/*****************************************************************************/
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_OSINTERFACE_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_OSINTERFACE_H
#define _OI_OSINTERFACE_H
/**
@file
* This file provides the platform-independent interface for functions for which
* implementation is platform-specific.
*
* The functions in this header file define the operating system or hardware
* services needed by the BLUEmagic 3.0 protocol stack. The
* actual implementation of these services is platform-dependent.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
#include "oi_time.h"
#include "oi_status.h"
#include "oi_modules.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Terminates execution.
*
* @param reason Reason for termination
*/
void OI_FatalError(OI_STATUS reason);
/**
* This function logs an error.
*
* When built for release mode, BLUEmagic 3 errors are logged to
* this function. (in debug mode, errors are logged via
* OI_Print()).
*
* @param module Module in which the error was detected (see
* oi_modules.h)
* @param lineno Line number of the C file OI_SLOG_ERROR called
* @param status Status code associated with the error event
*/
void OI_LogError(OI_MODULE module, OI_INT lineno, OI_STATUS status);
/**
* This function initializes the debug code handling.
*
* When built for debug mode, this function performs platform
* dependent initialization to handle message codes passed in
* via OI_SetMsgCode().
*/
void OI_InitDebugCodeHandler(void);
/**
* This function reads the time from the real time clock.
*
* All timing in BM3 is relative, typically a granularity
* of 5 or 10 msecs is adequate.
*
* @param[out] now Pointer to the buffer to which the current
* time will be returned
*/
void OI_Time_Now(OI_TIME *now);
/**
* This function causes the current thread to sleep for the
* specified amount of time. This function must be called
* without the stack access token.
*
* @note BM3 corestack and profiles never suspend and never call
* OI_Sleep. The use of OI_Sleep is limited to applications and
* platform-specific code.
*
* If your port and applications never use OI_Sleep, this function can be left unimplemented.
*
* @param milliseconds Number of milliseconds to sleep
*/
void OI_Sleep(OI_UINT32 milliseconds);
/**
* Defines for message type codes.
*/
#define OI_MSG_CODE_APPLICATION 0 /**< Application output */
#define OI_MSG_CODE_ERROR 1 /**< Error message output */
#define OI_MSG_CODE_WARNING 2 /**< Warning message output */
#define OI_MSG_CODE_TRACE 3 /**< User API function trace output */
#define OI_MSG_CODE_PRINT1 4 /**< Catagory 1 debug print output */
#define OI_MSG_CODE_PRINT2 5 /**< Catagory 2 debug print output */
#define OI_MSG_CODE_HEADER 6 /**< Error/Debug output header */
/**
* This function is used to indicate the type of text being output with
* OI_Print(). For the Linux and Win32 platforms, it will set
* the color of the text. Other possible uses could be to insert
* HTML style tags, add some other message type indication, or
* be completely ignored altogether.
*
* @param code OI_MSG_CODE_* indicating setting the message type.
*/
void OI_SetMsgCode(OI_UINT8 code);
/**
* All output from OI_Printf() and all debug output is sent to OI_Print.
* Typically, if the platform has a console, OI_Print() is sent to stdout.
* Embedded platforms typically send OI_Print() output to a serial port.
*
* @param str String to print
*/
void OI_Print(OI_CHAR const *str);
/**
* In cases where OI_Print() is sending output to a logfile in addition to console,
* it is desirable to also put console input into the logfile.
* This function can be called by the console input process.
*
* @note This is an optional API which is strictly
* between the platform-specific stack_console and osinterface
* modules. This API need only be implemented on those
* platforms where is serves a useful purpose, e.g., win32.
*
* @param str Console input string
*/
void OI_Print_ConsoleInput(OI_CHAR const *str);
/**
* This function computes the CRC16 of the program image.
*/
OI_UINT16 OI_ProgramImageCRC16(void);
/**
* Writes an integer to stdout in hex. This macro is intended
* for selective use when debugging in small memory
* configurations or other times when it is not possible to use
* OI_DBGPRINT.
*
* @param n the integer to print
*/
#define OI_Print_Int(n) \
{ \
static const OI_CHAR _digits[] = "0123456789ABCDEF"; \
OI_CHAR _buf[9]; \
OI_CHAR *_str = &_buf[8]; \
OI_UINT32 _i = n; \
*_str = 0; \
do { *(--_str) = _digits[(_i & 0xF)]; _i >>= 4; } while (_i); \
OI_Print(_str); \
}
/**
* Application Dynamic Memory allocation.
*
* These APIs are provided for application use on those
* platforms which have no dynamic memory support. Memory is
* allocated from the pool-based heap managed by the stack's
* internal memory manager.
*/
void *OI_APP_Malloc(OI_INT32 size);
void OI_APP_Free(void *ptr);
/*****************************************************************************/
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_OSINTERFACE_H */
File diff suppressed because it is too large Load Diff
+232 -232
View File
@@ -1,232 +1,232 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef OI_STDDEFS_H
#define OI_STDDEFS_H
/**
* @file
* This file contains BM3 standard type definitions.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_cpu_dep.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FALSE
#define FALSE 0 /**< This define statement sets FALSE as a preprocessor alias for 0. */
#endif
#ifndef TRUE
#define TRUE (!FALSE) /**< This define statement sets TRUE as a preprocessor alias for !FALSE. */
#endif
#ifdef HEW_TOOLCHAIN
#ifdef NULL
#undef NULL /**< Override HEW toolchain NULL definition */
#endif
#define NULL 0 /**< HEW toolchain does not allow us to compare (void*) type to function pointer */
#else
#ifndef NULL
#define NULL ((void*)0) /**< This define statement sets NULL as a preprocessor alias for (void*)0 */
#endif
#endif
/**
* @name Maximum and minimum values for basic types
* @{
*/
#define OI_INT8_MIN ((OI_INT8)0x80) /**< decimal value: -128 */
#define OI_INT8_MAX ((OI_INT8)0x7F) /**< decimal value: 127 */
#define OI_INT16_MIN ((OI_INT16)0x8000) /**< decimal value: -32768 */
#define OI_INT16_MAX ((OI_INT16)0x7FFF) /**< decimal value: 32767 */
#define OI_INT32_MIN ((OI_INT32)0x80000000) /**< decimal value: -2,147,483,648 */
#define OI_INT32_MAX ((OI_INT32)0x7FFFFFFF) /**< decimal value: 2,147,483,647 */
#define OI_UINT8_MIN ((OI_UINT8)0) /**< decimal value: 0 */
#define OI_UINT8_MAX ((OI_UINT8)0xFF) /**< decimal value: 255 */
#define OI_UINT16_MIN ((OI_UINT16)0) /**< decimal value: 0 */
#define OI_UINT16_MAX ((OI_UINT16)0xFFFF) /**< decimal value: 65535 */
#define OI_UINT32_MIN ((OI_UINT32)0) /**< decimal value: 0 */
#define OI_UINT32_MAX ((OI_UINT32)0xFFFFFFFF) /**< decimal value: 4,294,967,295 */
/**
* @}
*/
/**
* @name Integer types required by the Service Discovery Protocol
* @{
*/
/** unsigned 64-bit integer as a structure of two unsigned 32-bit integers */
typedef struct {
OI_UINT32 I1; /**< most significant 32 bits */
OI_UINT32 I2; /**< least significant 32 bits */
} OI_UINT64;
#define OI_UINT64_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_UINT64_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** signed 64-bit integer as a structure of one unsigned 32-bit integer and one signed 32-bit integer */
typedef struct {
OI_INT32 I1; /**< most significant 32 bits as a signed integer */
OI_UINT32 I2; /**< least significant 32 bits as an unsigned integer */
} OI_INT64;
#define OI_INT64_MIN { (OI_INT32)0x80000000, (OI_UINT32)0x00000000 }
#define OI_INT64_MAX { (OI_INT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** unsigned 128-bit integer as a structure of four unsigned 32-bit integers */
typedef struct {
OI_UINT32 I1; /**< most significant 32 bits */
OI_UINT32 I2; /**< second-most significant 32 bits */
OI_UINT32 I3; /**< third-most significant 32 bits */
OI_UINT32 I4; /**< least significant 32 bits */
} OI_UINT128;
#define OI_UINT128_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_UINT128_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** signed 128-bit integer as a structure of three unsigned 32-bit integers and one signed 32-bit integer */
typedef struct {
OI_INT32 I1; /**< most significant 32 bits as a signed integer */
OI_UINT32 I2; /**< second-most significant 32 bits as an unsigned integer */
OI_UINT32 I3; /**< third-most significant 32 bits as an unsigned integer */
OI_UINT32 I4; /**< least significant 32 bits as an unsigned integer */
} OI_INT128;
#define OI_INT128_MIN { (OI_UINT32)0x80000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_INT128_MAX { (OI_UINT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/**
* @}
*/
/**
* type for ASCII character data items
*/
typedef char OI_CHAR;
/**
* type for double-byte character data items
*/
typedef OI_UINT16 OI_CHAR16;
/**
* types for UTF encoded strings.
*/
typedef OI_UINT8 OI_UTF8;
typedef OI_UINT16 OI_UTF16;
typedef OI_UINT32 OI_UTF32;
/**
* @name Single-bit operation macros
* @{
* In these macros, x is the data item for which a bit is to be tested or set and y specifies which bit
* is to be tested or set.
*/
/** This macro's value is TRUE if the bit specified by y is set in data item x. */
#define OI_BIT_TEST(x,y) ((x) & (y))
/** This macro's value is TRUE if the bit specified by y is not set in data item x. */
#define OI_BIT_CLEAR_TEST(x,y) (((x) & (y)) == 0)
/** This macro sets the bit specified by y in data item x. */
#define OI_BIT_SET(x,y) ((x) |= (y))
/** This macro clears the bit specified by y in data item x. */
#define OI_BIT_CLEAR(x,y) ((x) &= ~(y))
/** @} */
/**
* The OI_ARRAYSIZE macro is set to the number of elements in an array
* (instead of the number of bytes, which is returned by sizeof()).
*/
#ifndef OI_ARRAYSIZE
#define OI_ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
/**
* @name Preprocessor aliases for individual bit positions
* Bits are defined here only if they are not already defined.
* @{
*/
#ifndef BIT0
#define BIT0 0x00000001 /**< preprocessor alias for 32-bit value with bit 0 set, used to specify this single bit */
#define BIT1 0x00000002 /**< preprocessor alias for 32-bit value with bit 1 set, used to specify this single bit */
#define BIT2 0x00000004 /**< preprocessor alias for 32-bit value with bit 2 set, used to specify this single bit */
#define BIT3 0x00000008 /**< preprocessor alias for 32-bit value with bit 3 set, used to specify this single bit */
#define BIT4 0x00000010 /**< preprocessor alias for 32-bit value with bit 4 set, used to specify this single bit */
#define BIT5 0x00000020 /**< preprocessor alias for 32-bit value with bit 5 set, used to specify this single bit */
#define BIT6 0x00000040 /**< preprocessor alias for 32-bit value with bit 6 set, used to specify this single bit */
#define BIT7 0x00000080 /**< preprocessor alias for 32-bit value with bit 7 set, used to specify this single bit */
#define BIT8 0x00000100 /**< preprocessor alias for 32-bit value with bit 8 set, used to specify this single bit */
#define BIT9 0x00000200 /**< preprocessor alias for 32-bit value with bit 9 set, used to specify this single bit */
#define BIT10 0x00000400 /**< preprocessor alias for 32-bit value with bit 10 set, used to specify this single bit */
#define BIT11 0x00000800 /**< preprocessor alias for 32-bit value with bit 11 set, used to specify this single bit */
#define BIT12 0x00001000 /**< preprocessor alias for 32-bit value with bit 12 set, used to specify this single bit */
#define BIT13 0x00002000 /**< preprocessor alias for 32-bit value with bit 13 set, used to specify this single bit */
#define BIT14 0x00004000 /**< preprocessor alias for 32-bit value with bit 14 set, used to specify this single bit */
#define BIT15 0x00008000 /**< preprocessor alias for 32-bit value with bit 15 set, used to specify this single bit */
#define BIT16 0x00010000 /**< preprocessor alias for 32-bit value with bit 16 set, used to specify this single bit */
#define BIT17 0x00020000 /**< preprocessor alias for 32-bit value with bit 17 set, used to specify this single bit */
#define BIT18 0x00040000 /**< preprocessor alias for 32-bit value with bit 18 set, used to specify this single bit */
#define BIT19 0x00080000 /**< preprocessor alias for 32-bit value with bit 19 set, used to specify this single bit */
#define BIT20 0x00100000 /**< preprocessor alias for 32-bit value with bit 20 set, used to specify this single bit */
#define BIT21 0x00200000 /**< preprocessor alias for 32-bit value with bit 21 set, used to specify this single bit */
#define BIT22 0x00400000 /**< preprocessor alias for 32-bit value with bit 22 set, used to specify this single bit */
#define BIT23 0x00800000 /**< preprocessor alias for 32-bit value with bit 23 set, used to specify this single bit */
#define BIT24 0x01000000 /**< preprocessor alias for 32-bit value with bit 24 set, used to specify this single bit */
#define BIT25 0x02000000 /**< preprocessor alias for 32-bit value with bit 25 set, used to specify this single bit */
#define BIT26 0x04000000 /**< preprocessor alias for 32-bit value with bit 26 set, used to specify this single bit */
#define BIT27 0x08000000 /**< preprocessor alias for 32-bit value with bit 27 set, used to specify this single bit */
#define BIT28 0x10000000 /**< preprocessor alias for 32-bit value with bit 28 set, used to specify this single bit */
#define BIT29 0x20000000 /**< preprocessor alias for 32-bit value with bit 29 set, used to specify this single bit */
#define BIT30 0x40000000 /**< preprocessor alias for 32-bit value with bit 30 set, used to specify this single bit */
#define BIT31 0x80000000 /**< preprocessor alias for 32-bit value with bit 31 set, used to specify this single bit */
#endif /* BIT0 et al */
/** @} */
#ifdef __cplusplus
}
#endif
/**@}*/
/*****************************************************************************/
#endif /* OI_STDDEFS_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef OI_STDDEFS_H
#define OI_STDDEFS_H
/**
* @file
* This file contains BM3 standard type definitions.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_cpu_dep.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef FALSE
#define FALSE 0 /**< This define statement sets FALSE as a preprocessor alias for 0. */
#endif
#ifndef TRUE
#define TRUE (!FALSE) /**< This define statement sets TRUE as a preprocessor alias for !FALSE. */
#endif
#ifdef HEW_TOOLCHAIN
#ifdef NULL
#undef NULL /**< Override HEW toolchain NULL definition */
#endif
#define NULL 0 /**< HEW toolchain does not allow us to compare (void*) type to function pointer */
#else
#ifndef NULL
#define NULL ((void*)0) /**< This define statement sets NULL as a preprocessor alias for (void*)0 */
#endif
#endif
/**
* @name Maximum and minimum values for basic types
* @{
*/
#define OI_INT8_MIN ((OI_INT8)0x80) /**< decimal value: -128 */
#define OI_INT8_MAX ((OI_INT8)0x7F) /**< decimal value: 127 */
#define OI_INT16_MIN ((OI_INT16)0x8000) /**< decimal value: -32768 */
#define OI_INT16_MAX ((OI_INT16)0x7FFF) /**< decimal value: 32767 */
#define OI_INT32_MIN ((OI_INT32)0x80000000) /**< decimal value: -2,147,483,648 */
#define OI_INT32_MAX ((OI_INT32)0x7FFFFFFF) /**< decimal value: 2,147,483,647 */
#define OI_UINT8_MIN ((OI_UINT8)0) /**< decimal value: 0 */
#define OI_UINT8_MAX ((OI_UINT8)0xFF) /**< decimal value: 255 */
#define OI_UINT16_MIN ((OI_UINT16)0) /**< decimal value: 0 */
#define OI_UINT16_MAX ((OI_UINT16)0xFFFF) /**< decimal value: 65535 */
#define OI_UINT32_MIN ((OI_UINT32)0) /**< decimal value: 0 */
#define OI_UINT32_MAX ((OI_UINT32)0xFFFFFFFF) /**< decimal value: 4,294,967,295 */
/**
* @}
*/
/**
* @name Integer types required by the Service Discovery Protocol
* @{
*/
/** unsigned 64-bit integer as a structure of two unsigned 32-bit integers */
typedef struct {
OI_UINT32 I1; /**< most significant 32 bits */
OI_UINT32 I2; /**< least significant 32 bits */
} OI_UINT64;
#define OI_UINT64_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_UINT64_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** signed 64-bit integer as a structure of one unsigned 32-bit integer and one signed 32-bit integer */
typedef struct {
OI_INT32 I1; /**< most significant 32 bits as a signed integer */
OI_UINT32 I2; /**< least significant 32 bits as an unsigned integer */
} OI_INT64;
#define OI_INT64_MIN { (OI_INT32)0x80000000, (OI_UINT32)0x00000000 }
#define OI_INT64_MAX { (OI_INT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** unsigned 128-bit integer as a structure of four unsigned 32-bit integers */
typedef struct {
OI_UINT32 I1; /**< most significant 32 bits */
OI_UINT32 I2; /**< second-most significant 32 bits */
OI_UINT32 I3; /**< third-most significant 32 bits */
OI_UINT32 I4; /**< least significant 32 bits */
} OI_UINT128;
#define OI_UINT128_MIN { (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_UINT128_MAX { (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/** signed 128-bit integer as a structure of three unsigned 32-bit integers and one signed 32-bit integer */
typedef struct {
OI_INT32 I1; /**< most significant 32 bits as a signed integer */
OI_UINT32 I2; /**< second-most significant 32 bits as an unsigned integer */
OI_UINT32 I3; /**< third-most significant 32 bits as an unsigned integer */
OI_UINT32 I4; /**< least significant 32 bits as an unsigned integer */
} OI_INT128;
#define OI_INT128_MIN { (OI_UINT32)0x80000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000, (OI_UINT32)0x00000000 }
#define OI_INT128_MAX { (OI_UINT32)0X7FFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF, (OI_UINT32)0XFFFFFFFF }
/**
* @}
*/
/**
* type for ASCII character data items
*/
typedef char OI_CHAR;
/**
* type for double-byte character data items
*/
typedef OI_UINT16 OI_CHAR16;
/**
* types for UTF encoded strings.
*/
typedef OI_UINT8 OI_UTF8;
typedef OI_UINT16 OI_UTF16;
typedef OI_UINT32 OI_UTF32;
/**
* @name Single-bit operation macros
* @{
* In these macros, x is the data item for which a bit is to be tested or set and y specifies which bit
* is to be tested or set.
*/
/** This macro's value is TRUE if the bit specified by y is set in data item x. */
#define OI_BIT_TEST(x,y) ((x) & (y))
/** This macro's value is TRUE if the bit specified by y is not set in data item x. */
#define OI_BIT_CLEAR_TEST(x,y) (((x) & (y)) == 0)
/** This macro sets the bit specified by y in data item x. */
#define OI_BIT_SET(x,y) ((x) |= (y))
/** This macro clears the bit specified by y in data item x. */
#define OI_BIT_CLEAR(x,y) ((x) &= ~(y))
/** @} */
/**
* The OI_ARRAYSIZE macro is set to the number of elements in an array
* (instead of the number of bytes, which is returned by sizeof()).
*/
#ifndef OI_ARRAYSIZE
#define OI_ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
/**
* @name Preprocessor aliases for individual bit positions
* Bits are defined here only if they are not already defined.
* @{
*/
#ifndef BIT0
#define BIT0 0x00000001 /**< preprocessor alias for 32-bit value with bit 0 set, used to specify this single bit */
#define BIT1 0x00000002 /**< preprocessor alias for 32-bit value with bit 1 set, used to specify this single bit */
#define BIT2 0x00000004 /**< preprocessor alias for 32-bit value with bit 2 set, used to specify this single bit */
#define BIT3 0x00000008 /**< preprocessor alias for 32-bit value with bit 3 set, used to specify this single bit */
#define BIT4 0x00000010 /**< preprocessor alias for 32-bit value with bit 4 set, used to specify this single bit */
#define BIT5 0x00000020 /**< preprocessor alias for 32-bit value with bit 5 set, used to specify this single bit */
#define BIT6 0x00000040 /**< preprocessor alias for 32-bit value with bit 6 set, used to specify this single bit */
#define BIT7 0x00000080 /**< preprocessor alias for 32-bit value with bit 7 set, used to specify this single bit */
#define BIT8 0x00000100 /**< preprocessor alias for 32-bit value with bit 8 set, used to specify this single bit */
#define BIT9 0x00000200 /**< preprocessor alias for 32-bit value with bit 9 set, used to specify this single bit */
#define BIT10 0x00000400 /**< preprocessor alias for 32-bit value with bit 10 set, used to specify this single bit */
#define BIT11 0x00000800 /**< preprocessor alias for 32-bit value with bit 11 set, used to specify this single bit */
#define BIT12 0x00001000 /**< preprocessor alias for 32-bit value with bit 12 set, used to specify this single bit */
#define BIT13 0x00002000 /**< preprocessor alias for 32-bit value with bit 13 set, used to specify this single bit */
#define BIT14 0x00004000 /**< preprocessor alias for 32-bit value with bit 14 set, used to specify this single bit */
#define BIT15 0x00008000 /**< preprocessor alias for 32-bit value with bit 15 set, used to specify this single bit */
#define BIT16 0x00010000 /**< preprocessor alias for 32-bit value with bit 16 set, used to specify this single bit */
#define BIT17 0x00020000 /**< preprocessor alias for 32-bit value with bit 17 set, used to specify this single bit */
#define BIT18 0x00040000 /**< preprocessor alias for 32-bit value with bit 18 set, used to specify this single bit */
#define BIT19 0x00080000 /**< preprocessor alias for 32-bit value with bit 19 set, used to specify this single bit */
#define BIT20 0x00100000 /**< preprocessor alias for 32-bit value with bit 20 set, used to specify this single bit */
#define BIT21 0x00200000 /**< preprocessor alias for 32-bit value with bit 21 set, used to specify this single bit */
#define BIT22 0x00400000 /**< preprocessor alias for 32-bit value with bit 22 set, used to specify this single bit */
#define BIT23 0x00800000 /**< preprocessor alias for 32-bit value with bit 23 set, used to specify this single bit */
#define BIT24 0x01000000 /**< preprocessor alias for 32-bit value with bit 24 set, used to specify this single bit */
#define BIT25 0x02000000 /**< preprocessor alias for 32-bit value with bit 25 set, used to specify this single bit */
#define BIT26 0x04000000 /**< preprocessor alias for 32-bit value with bit 26 set, used to specify this single bit */
#define BIT27 0x08000000 /**< preprocessor alias for 32-bit value with bit 27 set, used to specify this single bit */
#define BIT28 0x10000000 /**< preprocessor alias for 32-bit value with bit 28 set, used to specify this single bit */
#define BIT29 0x20000000 /**< preprocessor alias for 32-bit value with bit 29 set, used to specify this single bit */
#define BIT30 0x40000000 /**< preprocessor alias for 32-bit value with bit 30 set, used to specify this single bit */
#define BIT31 0x80000000 /**< preprocessor alias for 32-bit value with bit 31 set, used to specify this single bit */
#endif /* BIT0 et al */
/** @} */
#ifdef __cplusplus
}
#endif
/**@}*/
/*****************************************************************************/
#endif /* OI_STDDEFS_H */
+208 -208
View File
@@ -1,208 +1,208 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef OI_STRING_H
#define OI_STRING_H
/**
* @file
* This file contains BM3 supplied portable string.h functions
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_cpu_dep.h"
#include "oi_stddefs.h"
#if defined(USE_NATIVE_MEMCPY) || defined(USE_NATIVE_MALLOC)
#include <string.h>
#endif
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* If we are using Native malloc(), we must also use
* native Ansi string.h functions for memory manipulation.
*/
#ifdef USE_NATIVE_MALLOC
#ifndef USE_NATIVE_MEMCPY
#define USE_NATIVE_MEMCPY
#endif
#endif
#ifdef USE_NATIVE_MEMCPY
#define OI_MemCopy(to, from, size) memcpy((to), (from), (size))
#define OI_MemSet(block, val, size) memset((block), (val), (size))
#define OI_MemZero(block, size) memset((block), 0, (size))
#define OI_MemCmp(s1, s2, n) memcmp((s1), (s2), (n))
#define OI_Strcpy(dest, src) strcpy((dest),(src))
#define OI_Strcat(dest, src) strcat((dest),(src))
#define OI_StrLen(str) strlen((str))
#define OI_Strcmp(s1, s2) strcmp((s1), (s2))
#define OI_Strncmp(s1, s2, n) strncmp((s1), (s2), (n))
#else
/*
* OI_MemCopy
*
* Copy an arbitrary number of bytes from one memory address to another.
* The underlying implementation is the ANSI memmove() or equivalant, so
* overlapping memory copies will work correctly.
*/
void OI_MemCopy(void *To, void const *From, OI_UINT32 Size);
/*
* OI_MemSet
*
* Sets all bytes in a block of memory to the same value
*/
void OI_MemSet(void *Block, OI_UINT8 Val, OI_UINT32 Size);
/*
* OI_MemZero
*
* Sets all bytes in a block of memory to zero
*/
void OI_MemZero(void *Block, OI_UINT32 Size);
/*
* OI_MemCmp
*
* Compare two blocks of memory
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_MemCmp(void const *s1, void const *s2, OI_UINT32 n);
/*
* OI_Strcpy
*
* Copies the Null terminated string from pStr to pDest, and
* returns pDest.
*/
OI_CHAR* OI_Strcpy(OI_CHAR *pDest,
OI_CHAR const *pStr);
/*
* OI_Strcat
*
* Concatonates the pStr string to the end of pDest, and
* returns pDest.
*/
OI_CHAR* OI_Strcat(OI_CHAR *pDest,
OI_CHAR const *pStr) ;
/*
* OI_StrLen
*
* Calculates the number of OI_CHARs in pStr (not including
* the Null terminator) and returns the value.
*/
OI_UINT OI_StrLen(OI_CHAR const *pStr) ;
/*
* OI_Strcmp
*
* Compares two Null terminated strings
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_Strcmp(OI_CHAR const *s1,
OI_CHAR const *s2);
/*
* OI_Strncmp
*
* Compares the first "len" OI_CHARs of strings s1 and s2.
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_Strncmp(OI_CHAR const *s1,
OI_CHAR const *s2,
OI_UINT32 len);
#endif /* USE_NATIVE_MEMCPY */
/*
* OI_StrcmpInsensitive
*
* Compares two Null terminated strings, treating
* the Upper and Lower case of 'A' through 'Z' as
* equivilent.
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_StrcmpInsensitive(OI_CHAR const *s1,
OI_CHAR const *s2);
/*
* OI_StrncmpInsensitive
*
* Compares the first "len" OI_CHARs of strings s1 and s2,
* treating the Upper and Lower case of 'A' through 'Z' as
* equivilent.
*
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_StrncmpInsensitive(OI_CHAR const *s1,
OI_CHAR const *s2,
OI_UINT len);
#ifdef __cplusplus
}
#endif
/** @} */
/*****************************************************************************/
#endif /* OI_STRING_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef OI_STRING_H
#define OI_STRING_H
/**
* @file
* This file contains BM3 supplied portable string.h functions
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_cpu_dep.h"
#include "oi_stddefs.h"
#if defined(USE_NATIVE_MEMCPY) || defined(USE_NATIVE_MALLOC)
#include <string.h>
#endif
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/*
* If we are using Native malloc(), we must also use
* native Ansi string.h functions for memory manipulation.
*/
#ifdef USE_NATIVE_MALLOC
#ifndef USE_NATIVE_MEMCPY
#define USE_NATIVE_MEMCPY
#endif
#endif
#ifdef USE_NATIVE_MEMCPY
#define OI_MemCopy(to, from, size) memcpy((to), (from), (size))
#define OI_MemSet(block, val, size) memset((block), (val), (size))
#define OI_MemZero(block, size) memset((block), 0, (size))
#define OI_MemCmp(s1, s2, n) memcmp((s1), (s2), (n))
#define OI_Strcpy(dest, src) strcpy((dest),(src))
#define OI_Strcat(dest, src) strcat((dest),(src))
#define OI_StrLen(str) strlen((str))
#define OI_Strcmp(s1, s2) strcmp((s1), (s2))
#define OI_Strncmp(s1, s2, n) strncmp((s1), (s2), (n))
#else
/*
* OI_MemCopy
*
* Copy an arbitrary number of bytes from one memory address to another.
* The underlying implementation is the ANSI memmove() or equivalant, so
* overlapping memory copies will work correctly.
*/
void OI_MemCopy(void *To, void const *From, OI_UINT32 Size);
/*
* OI_MemSet
*
* Sets all bytes in a block of memory to the same value
*/
void OI_MemSet(void *Block, OI_UINT8 Val, OI_UINT32 Size);
/*
* OI_MemZero
*
* Sets all bytes in a block of memory to zero
*/
void OI_MemZero(void *Block, OI_UINT32 Size);
/*
* OI_MemCmp
*
* Compare two blocks of memory
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_MemCmp(void const *s1, void const *s2, OI_UINT32 n);
/*
* OI_Strcpy
*
* Copies the Null terminated string from pStr to pDest, and
* returns pDest.
*/
OI_CHAR* OI_Strcpy(OI_CHAR *pDest,
OI_CHAR const *pStr);
/*
* OI_Strcat
*
* Concatonates the pStr string to the end of pDest, and
* returns pDest.
*/
OI_CHAR* OI_Strcat(OI_CHAR *pDest,
OI_CHAR const *pStr) ;
/*
* OI_StrLen
*
* Calculates the number of OI_CHARs in pStr (not including
* the Null terminator) and returns the value.
*/
OI_UINT OI_StrLen(OI_CHAR const *pStr) ;
/*
* OI_Strcmp
*
* Compares two Null terminated strings
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_Strcmp(OI_CHAR const *s1,
OI_CHAR const *s2);
/*
* OI_Strncmp
*
* Compares the first "len" OI_CHARs of strings s1 and s2.
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_Strncmp(OI_CHAR const *s1,
OI_CHAR const *s2,
OI_UINT32 len);
#endif /* USE_NATIVE_MEMCPY */
/*
* OI_StrcmpInsensitive
*
* Compares two Null terminated strings, treating
* the Upper and Lower case of 'A' through 'Z' as
* equivilent.
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_StrcmpInsensitive(OI_CHAR const *s1,
OI_CHAR const *s2);
/*
* OI_StrncmpInsensitive
*
* Compares the first "len" OI_CHARs of strings s1 and s2,
* treating the Upper and Lower case of 'A' through 'Z' as
* equivilent.
*
*
* Returns:
* 0, if s1 == s2
* < 0, if s1 < s2
* > 0, if s2 > s2
*/
OI_INT OI_StrncmpInsensitive(OI_CHAR const *s1,
OI_CHAR const *s2,
OI_UINT len);
#ifdef __cplusplus
}
#endif
/** @} */
/*****************************************************************************/
#endif /* OI_STRING_H */
+200 -200
View File
@@ -1,200 +1,200 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_TIME_H
#define _OI_TIME_H
/** @file
*
* This file provides time type definitions and interfaces to time-related functions.
*
* The stack maintains a 64-bit real-time millisecond clock. The choice of
* milliseconds is for convenience, not accuracy.
*
* Timeouts are specified as tenths of seconds in a 32-bit value. Timeout values
* specified by the Bluetooth specification are usually muliple seconds, so
* accuracy to a tenth of a second is more than adequate.
*
* This file also contains macros to convert between seconds and the Link
* Manager's 1.28-second units.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Within the core stack timeouts are specified in intervals of tenths of seconds
*/
typedef OI_UINT16 OI_INTERVAL;
#define OI_INTERVALS_PER_SECOND 10
#define MSECS_PER_OI_INTERVAL (1000 / OI_INTERVALS_PER_SECOND)
/** maximum interval (54 min 36.7 sec) */
#define OI_MAX_INTERVAL 0x7fff
/**
* Macro to convert seconds to OI_INTERVAL time units
*/
#define OI_SECONDS(n) ((OI_INTERVAL) ((n) * OI_INTERVALS_PER_SECOND))
/**
* Macro to convert milliseconds to OI_INTERVAL time units (Rounded Up)
*/
#define OI_MSECONDS(n) ((OI_INTERVAL) ((n + MSECS_PER_OI_INTERVAL - 1) / MSECS_PER_OI_INTERVAL))
/**
* Macro to convert minutes to OI_INTERVAL time units
*/
#define OI_MINUTES(n) ((OI_INTERVAL) ((n) * OI_SECONDS(60)))
/** Convert an OI_INTERVAL to milliseconds. */
#define OI_INTERVAL_TO_MILLISECONDS(i) ((i) * MSECS_PER_OI_INTERVAL)
/**
* The stack depends on relative not absolute time. Any mapping between the
* stack's real-time clock and absolute time and date is implementation-dependent.
*/
typedef struct {
OI_INT32 seconds;
OI_INT16 mseconds;
} OI_TIME;
/**
* Convert an OI_TIME to milliseconds.
*
* @param t the time to convert
*
* @return the time in milliseconds
*/
OI_UINT32 OI_Time_ToMS(OI_TIME *t);
/**
* This function compares two time values.
*
* @param T1 first time to compare.
*
* @param T2 second time to compare.
*
* @return
@verbatim
-1 if t1 < t2
0 if t1 = t2
+1 if t1 > t2
@endverbatim
*/
OI_INT16 OI_Time_Compare(OI_TIME *T1,
OI_TIME *T2);
/**
* This function returns the interval between two times to a granularity of 0.1 seconds.
*
* @param Sooner a time value more recent that Later
*
* @param Later a time value later than Sooner
*
* @note The result is an OI_INTERVAL value so this function only works for time intervals
* that are less than about 71 minutes.
*
* @return the time interval between the two times = (Later - Sooner)
*/
OI_INTERVAL OI_Time_Interval(OI_TIME *Sooner,
OI_TIME *Later);
/**
* This function returns the interval between two times to a granularity of milliseconds.
*
* @param Sooner a time value more recent that Later
*
* @param Later a time value later than Sooner
*
* @note The result is an OI_UINT32 value so this function only works for time intervals
* that are less than about 50 days.
*
* @return the time interval between the two times = (Later - Sooner)
*/
OI_UINT32 OI_Time_IntervalMsecs(OI_TIME *Sooner,
OI_TIME *Later);
/**
* This function answers the question, Have we reached or gone past the target time?
*
* @param pTargetTime target time
*
* @return TRUE means time now is at or past target time
* FALSE means target time is still some time in the future
*/
OI_BOOL OI_Time_NowReachedTime(OI_TIME *pTargetTime);
/**
* Convert seconds to the Link Manager 1.28-second units
* Approximate by using 1.25 conversion factor.
*/
#define OI_SECONDS_TO_LM_TIME_UNITS(lmUnits) ((lmUnits)<4?(lmUnits):(lmUnits)-((lmUnits)>>2))
/**
* Convert Link Manager 1.28-second units to seconds.
* Approximate by using 1.25 conversion factor.
*/
#define OI_LM_TIME_UNITS_TO_SECONDS(lmUnits) ((lmUnits) + ((lmUnits)>>2))
#ifdef __cplusplus
}
#endif
/**@}*/
/* Include for OI_Time_Now() prototype
* Must be included at end to obtain OI_TIME typedef
*/
#include "oi_osinterface.h"
/*****************************************************************************/
#endif /* _OI_TIME_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_TIME_H
#define _OI_TIME_H
/** @file
*
* This file provides time type definitions and interfaces to time-related functions.
*
* The stack maintains a 64-bit real-time millisecond clock. The choice of
* milliseconds is for convenience, not accuracy.
*
* Timeouts are specified as tenths of seconds in a 32-bit value. Timeout values
* specified by the Bluetooth specification are usually muliple seconds, so
* accuracy to a tenth of a second is more than adequate.
*
* This file also contains macros to convert between seconds and the Link
* Manager's 1.28-second units.
*
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Within the core stack timeouts are specified in intervals of tenths of seconds
*/
typedef OI_UINT16 OI_INTERVAL;
#define OI_INTERVALS_PER_SECOND 10
#define MSECS_PER_OI_INTERVAL (1000 / OI_INTERVALS_PER_SECOND)
/** maximum interval (54 min 36.7 sec) */
#define OI_MAX_INTERVAL 0x7fff
/**
* Macro to convert seconds to OI_INTERVAL time units
*/
#define OI_SECONDS(n) ((OI_INTERVAL) ((n) * OI_INTERVALS_PER_SECOND))
/**
* Macro to convert milliseconds to OI_INTERVAL time units (Rounded Up)
*/
#define OI_MSECONDS(n) ((OI_INTERVAL) ((n + MSECS_PER_OI_INTERVAL - 1) / MSECS_PER_OI_INTERVAL))
/**
* Macro to convert minutes to OI_INTERVAL time units
*/
#define OI_MINUTES(n) ((OI_INTERVAL) ((n) * OI_SECONDS(60)))
/** Convert an OI_INTERVAL to milliseconds. */
#define OI_INTERVAL_TO_MILLISECONDS(i) ((i) * MSECS_PER_OI_INTERVAL)
/**
* The stack depends on relative not absolute time. Any mapping between the
* stack's real-time clock and absolute time and date is implementation-dependent.
*/
typedef struct {
OI_INT32 seconds;
OI_INT16 mseconds;
} OI_TIME;
/**
* Convert an OI_TIME to milliseconds.
*
* @param t the time to convert
*
* @return the time in milliseconds
*/
OI_UINT32 OI_Time_ToMS(OI_TIME *t);
/**
* This function compares two time values.
*
* @param T1 first time to compare.
*
* @param T2 second time to compare.
*
* @return
@verbatim
-1 if t1 < t2
0 if t1 = t2
+1 if t1 > t2
@endverbatim
*/
OI_INT16 OI_Time_Compare(OI_TIME *T1,
OI_TIME *T2);
/**
* This function returns the interval between two times to a granularity of 0.1 seconds.
*
* @param Sooner a time value more recent that Later
*
* @param Later a time value later than Sooner
*
* @note The result is an OI_INTERVAL value so this function only works for time intervals
* that are less than about 71 minutes.
*
* @return the time interval between the two times = (Later - Sooner)
*/
OI_INTERVAL OI_Time_Interval(OI_TIME *Sooner,
OI_TIME *Later);
/**
* This function returns the interval between two times to a granularity of milliseconds.
*
* @param Sooner a time value more recent that Later
*
* @param Later a time value later than Sooner
*
* @note The result is an OI_UINT32 value so this function only works for time intervals
* that are less than about 50 days.
*
* @return the time interval between the two times = (Later - Sooner)
*/
OI_UINT32 OI_Time_IntervalMsecs(OI_TIME *Sooner,
OI_TIME *Later);
/**
* This function answers the question, Have we reached or gone past the target time?
*
* @param pTargetTime target time
*
* @return TRUE means time now is at or past target time
* FALSE means target time is still some time in the future
*/
OI_BOOL OI_Time_NowReachedTime(OI_TIME *pTargetTime);
/**
* Convert seconds to the Link Manager 1.28-second units
* Approximate by using 1.25 conversion factor.
*/
#define OI_SECONDS_TO_LM_TIME_UNITS(lmUnits) ((lmUnits)<4?(lmUnits):(lmUnits)-((lmUnits)>>2))
/**
* Convert Link Manager 1.28-second units to seconds.
* Approximate by using 1.25 conversion factor.
*/
#define OI_LM_TIME_UNITS_TO_SECONDS(lmUnits) ((lmUnits) + ((lmUnits)>>2))
#ifdef __cplusplus
}
#endif
/**@}*/
/* Include for OI_Time_Now() prototype
* Must be included at end to obtain OI_TIME typedef
*/
#include "oi_osinterface.h"
/*****************************************************************************/
#endif /* _OI_TIME_H */
+377 -377
View File
@@ -1,377 +1,377 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_UTILS_H
#define _OI_UTILS_H
/**
* @file
*
* This file provides the interface for utility functions.
* Among the utilities are strlen (string length), strcmp (string compare), and
* other string manipulation functions. These are provided for those plaforms
* where this functionality is not available in stdlib.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include <stdarg.h>
#include "oi_common.h"
#include "oi_string.h"
#include "oi_bt_spec.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Opaque type for a callback function handle. See OI_ScheduleCallbackFunction()
*/
typedef OI_UINT32 OI_CALLBACK_HANDLE;
/**
* Function prototype for a timed procedure callback.
*
* @param arg Value that was passed into the OI_ScheduleCallback() function
*
*/
typedef void (*OI_SCHEDULED_CALLBACK)(void *arg);
/**
* Registers a function to be called when a timeout expires. This API uses BLUEmagic's internal
* function dispatch mechanism, so applications that make extensive use of this facility may need to
* increase the value of DispatchTableSize in the configuration block for the dispatcher (see
* oi_bt_stack_config.h).
*
* @param callbackFunction The function that will be called when the timeout expires
*
* @param arg Value that will be returned as the parameter to the callback function.
*
* @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be
* zero in which case the callback function will be called as soon as
* possible.
*
* @param handle NULL or a pointer receive the callback handle.
*
* @return OI_OK if the function was reqistered, or an error status.
*/
OI_STATUS OI_ScheduleCallbackFunction(OI_SCHEDULED_CALLBACK callbackFunction,
void *arg,
OI_INTERVAL timeout,
OI_CALLBACK_HANDLE *handle);
/**
* Cancels a function registered with OI_ScheduleCallbackFunction() before its timer expires.
*
* @param handle handle returned by OI_ScheduleCallbackFunction().
*
* @return OI_OK if the function was cancelled, or an error status.
*/
OI_STATUS OI_CancelCallbackFunction(OI_CALLBACK_HANDLE handle);
/**
* Registers a function to be called when a timeout expires. This version does not return a handle
* so can only be canceled by calling OI_CancelCallback().
*
* @param callbackFunction The function that will be called when the timeout expires
*
* @param arg Value that will be returned as the parameter to the callback function.
*
* @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be
* zero in which case the callback function will be called as soon as
* possible.
*
* @return OI_OK if the function was reqistered, or an error status.
*/
#define OI_ScheduleCallback(f, a, t) OI_ScheduleCallbackFunction(f, a, t, NULL);
/**
* Cancels a function registered with OI_ScheduleCallback() before its timer expires. This
* function will cancel the first entry matches the indicated callback function pointer.
*
* @param callbackFunction The function that was originally registered
*
* @return OI_OK if the function was cancelled, or an error status.
*/
OI_STATUS OI_CancelCallback(OI_SCHEDULED_CALLBACK callbackFunction);
/**
* Parse a Bluetooth device address from the specified string.
*
* @param str the string to parse
* @param addr the parsed address, if successful
*
* @return TRUE if an address was successfully parsed, FALSE otherwise
*/
OI_BOOL OI_ParseBdAddr(const OI_CHAR *str,
OI_BD_ADDR *addr) ;
/**
* Printf function for platforms which have no stdio or printf available.
* OI_Printf supports the basic formatting types, with the exception of
* floating point types. Additionally, OI_Printf supports several formats
* specific to BLUEmagic 3.0 software:
*
* \%! prints the string for an #OI_STATUS value.
* @code OI_Printf("There was an error %!", status); @endcode
*
* \%@ prints a hex dump of a buffer.
* Requires a pointer to the buffer and a signed integer length
* (0 for default length). If the buffer is large, only an excerpt will
* be printed.
* @code OI_Printf("Contents of buffer %@", buffer, sizeof(buffer)); @endcode
*
* \%: prints a Bluetooth address in the form "HH:HH:HH:HH:HH:HH".
* Requires a pointer to an #OI_BD_ADDR.
* @code OI_Printf("Bluetooth address %:", &bdaddr); @endcode
*
* \%^ decodes and prints a data element as formatted XML.
* Requires a pointer to an #OI_DATAELEM.
* @code OI_Printf("Service attribute list is:\n%^", &attributes); @endcode
*
* \%/ prints the base file name of a path, that is, the final substring
* following a '/' or '\\' character. Requires a pointer to a null
* terminated string.
* @code OI_Printf("File %/", "c:\\dir1\\dir2\\file.txt"); @endcode
*
* \%~ prints a string, escaping characters as needed to display it in
* ASCII. Requires a pointer to an #OI_PSTR and an #OI_UNICODE_ENCODING
* parameter.
* @code OI_Printf("Identifier %~", &id, OI_UNICODE_UTF16_BE); @endcode
*
* \%[ inserts an ANSI color escape sequence. Requires a single character
* identifying the color to select. Colors are red (r/R), green (g/G),
* blue (b/B), yellow (y/Y), cyan (c/C), magenta (m/M), white (W),
* light-gray (l/L), dark-gray (d/D), and black (0). The lower case is
* dim, the upper case is bright (except in the case of light-gray and
* dark-gray, where bright and dim are identical). Any other value will
* select the default color.
* @code OI_Printf("%[red text %[black %[normal\n", 'r', '0', 0); @endcode
*
* \%a same as \%s, except '\\r' and '\\n' are output as "<cr>" and "<lf>".
* \%?a is valid, but \%la is not.
*
* \%b prints an integer in base 2.
* @code OI_Printf("Bits are %b", I); @endcode
*
* \%lb prints a long integer in base 2.
*
* \%?b prints the least significant N bits of an integer (or long integer)
* in base 2. Requires the integer and a length N.
* @code OI_Printf("Bottom 4 bits are: %?b", I, 4); @endcode
*
* \%B prints an integer as boolean text, "TRUE" or "FALSE".
* @code OI_Printf("The value 0 is %B, the value 1 is %B", 0, 1); @endcode
*
* \%?s prints a substring up to a specified maximum length.
* Requires a pointer to a string and a length parameter.
* @code OI_Printf("String prefix is %?s", str, 3); @endcode
*
* \%ls same as \%S.
*
* \%S prints a UTF16 string as UTF8 (plain ASCII, plus 8-bit char sequences
* where needed). Requires a pointer to #OI_CHAR16. \%?S is valid. The
* length parameter is in OI_CHAR16 characters.
*
* \%T prints time, formatted as "secs.msecs".
* Requires pointer to #OI_TIME struct, NULL pointer prints current time.
* @code OI_Printf("The time now is %T", NULL); @endcode
*
* @param format The format string
*
*/
void OI_Printf(const OI_CHAR *format, ...);
/**
* Var-args version OI_Printf
*
* @param format Same as for OI_Printf.
*
* @param argp Var-args list.
*/
void OI_VPrintf(const OI_CHAR *format, va_list argp);
/**
* Writes a formatted string to a buffer. This function supports the same format specifiers as
* OI_Printf().
*
* @param buffer Destination buffer for the formatted string.
*
* @param bufLen The length of the destination buffer.
*
* @param format The format string
*
* @return Number of characters written or -1 in the case of an error.
*/
OI_INT32 OI_SNPrintf(OI_CHAR *buffer,
OI_UINT16 bufLen,
const OI_CHAR* format, ...);
/**
* Var-args version OI_SNPrintf
*
* @param buffer Destination buffer for the formatted string.
*
* @param bufLen The length of the destination buffer.
*
* @param format The format string
*
* @param argp Var-args list.
*
* @return Number of characters written or -1 in the case of an error.
*/
OI_INT32 OI_VSNPrintf(OI_CHAR *buffer,
OI_UINT16 bufLen,
const OI_CHAR *format, va_list argp);
/**
* Convert a string to an integer.
*
* @param str the string to parse
*
* @return the integer value of the string or 0 if the string could not be parsed
*/
OI_INT OI_atoi(const OI_CHAR *str);
/**
* Parse a signed integer in a string.
*
* Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string
* must be prefixed by "0x". Returns pointer to first character following the integer. Returns the
* pointer passed in if the string does not describe an integer.
*
* @param str String to parse.
*
* @param val Pointer to receive the parsed integer value.
*
* @return A pointer to the first character following the integer or the pointer passed in.
*/
const OI_CHAR* OI_ScanInt(const OI_CHAR *str,
OI_INT32 *val);
/**
* Parse an unsigned integer in a string.
*
* Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string
* must be prefixed by "0x". Returns pointer to first character following the integer. Returns the
* pointer passed in if the string does not describe an integer.
*
* @param str String to parse.
*
* @param val Pointer to receive the parsed unsigned integer value.
*
* @return A pointer to the first character following the unsigned integer or the pointer passed in.
*/
const OI_CHAR* OI_ScanUInt(const OI_CHAR *str,
OI_UINT32 *val);
/**
* Parse a whitespace delimited substring out of a string.
*
* @param str Input string to parse.
* @param outStr Buffer to return the substring
* @param len Length of outStr
*
*
* @return A pointer to the first character following the substring or the pointer passed in.
*/
const OI_CHAR* OI_ScanStr(const OI_CHAR *str,
OI_CHAR *outStr,
OI_UINT16 len);
/**
* Parse a string for one of a set of alternative value. Skips leading whitespace (space and tabs
* only) and parses text matching one of the alternative strings. Returns pointer to first character
* following the matched text.
*
* @param str String to parse.
*
* @param alts Alternative matching strings separated by '|'
*
* @param index Pointer to receive the index of the matching alternative, return value is -1 if
* there is no match.
*
* @return A pointer to the first character following the matched value or the pointer passed in
* if there was no matching text.
*/
const OI_CHAR* OI_ScanAlt(const OI_CHAR *str,
const OI_CHAR *alts,
OI_INT *index);
/**
* Parse a string for a BD Addr. Skips leading whitespace (space and tabs only) and parses a
* Bluetooth device address with nibbles optionally separated by colons. Return pointet to first
* character following the BD Addr.
*
* @param str String to parse.
*
* @param addr Pointer to receive the Bluetooth device address
*
* @return A pointer to the first character following the BD Addr or the pointer passed in.
*/
const OI_CHAR* OI_ScanBdAddr(const OI_CHAR *str,
OI_BD_ADDR *addr);
/** Get a character from a digit integer value (0 - 9). */
#define OI_DigitToChar(d) ((d) + '0')
/**
* Determine Maximum and Minimum between two arguments.
*
* @param a 1st value
* @param b 2nd value
*
* @return the max or min value between a & b
*/
#define OI_MAX(a, b) (((a) < (b)) ? (b) : (a) )
#define OI_MIN(a, b) (((a) > (b)) ? (b) : (a) )
/**
* Compare two BD_ADDRs
* SAME_BD_ADDR - Boolean: TRUE if they are the same address
*/
#define SAME_BD_ADDR(x, y) (0 == OI_MemCmp((x),(y),OI_BD_ADDR_BYTE_SIZE) )
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_UTILS_H */
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
#ifndef _OI_UTILS_H
#define _OI_UTILS_H
/**
* @file
*
* This file provides the interface for utility functions.
* Among the utilities are strlen (string length), strcmp (string compare), and
* other string manipulation functions. These are provided for those plaforms
* where this functionality is not available in stdlib.
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include <stdarg.h>
#include "oi_common.h"
#include "oi_string.h"
#include "oi_bt_spec.h"
/** \addtogroup Misc Miscellaneous APIs */
/**@{*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Opaque type for a callback function handle. See OI_ScheduleCallbackFunction()
*/
typedef OI_UINT32 OI_CALLBACK_HANDLE;
/**
* Function prototype for a timed procedure callback.
*
* @param arg Value that was passed into the OI_ScheduleCallback() function
*
*/
typedef void (*OI_SCHEDULED_CALLBACK)(void *arg);
/**
* Registers a function to be called when a timeout expires. This API uses BLUEmagic's internal
* function dispatch mechanism, so applications that make extensive use of this facility may need to
* increase the value of DispatchTableSize in the configuration block for the dispatcher (see
* oi_bt_stack_config.h).
*
* @param callbackFunction The function that will be called when the timeout expires
*
* @param arg Value that will be returned as the parameter to the callback function.
*
* @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be
* zero in which case the callback function will be called as soon as
* possible.
*
* @param handle NULL or a pointer receive the callback handle.
*
* @return OI_OK if the function was reqistered, or an error status.
*/
OI_STATUS OI_ScheduleCallbackFunction(OI_SCHEDULED_CALLBACK callbackFunction,
void *arg,
OI_INTERVAL timeout,
OI_CALLBACK_HANDLE *handle);
/**
* Cancels a function registered with OI_ScheduleCallbackFunction() before its timer expires.
*
* @param handle handle returned by OI_ScheduleCallbackFunction().
*
* @return OI_OK if the function was cancelled, or an error status.
*/
OI_STATUS OI_CancelCallbackFunction(OI_CALLBACK_HANDLE handle);
/**
* Registers a function to be called when a timeout expires. This version does not return a handle
* so can only be canceled by calling OI_CancelCallback().
*
* @param callbackFunction The function that will be called when the timeout expires
*
* @param arg Value that will be returned as the parameter to the callback function.
*
* @param timeout A timeout expressed in OI_INTERVALs (tenths of seconds). This can be
* zero in which case the callback function will be called as soon as
* possible.
*
* @return OI_OK if the function was reqistered, or an error status.
*/
#define OI_ScheduleCallback(f, a, t) OI_ScheduleCallbackFunction(f, a, t, NULL);
/**
* Cancels a function registered with OI_ScheduleCallback() before its timer expires. This
* function will cancel the first entry matches the indicated callback function pointer.
*
* @param callbackFunction The function that was originally registered
*
* @return OI_OK if the function was cancelled, or an error status.
*/
OI_STATUS OI_CancelCallback(OI_SCHEDULED_CALLBACK callbackFunction);
/**
* Parse a Bluetooth device address from the specified string.
*
* @param str the string to parse
* @param addr the parsed address, if successful
*
* @return TRUE if an address was successfully parsed, FALSE otherwise
*/
OI_BOOL OI_ParseBdAddr(const OI_CHAR *str,
OI_BD_ADDR *addr) ;
/**
* Printf function for platforms which have no stdio or printf available.
* OI_Printf supports the basic formatting types, with the exception of
* floating point types. Additionally, OI_Printf supports several formats
* specific to BLUEmagic 3.0 software:
*
* \%! prints the string for an #OI_STATUS value.
* @code OI_Printf("There was an error %!", status); @endcode
*
* \%@ prints a hex dump of a buffer.
* Requires a pointer to the buffer and a signed integer length
* (0 for default length). If the buffer is large, only an excerpt will
* be printed.
* @code OI_Printf("Contents of buffer %@", buffer, sizeof(buffer)); @endcode
*
* \%: prints a Bluetooth address in the form "HH:HH:HH:HH:HH:HH".
* Requires a pointer to an #OI_BD_ADDR.
* @code OI_Printf("Bluetooth address %:", &bdaddr); @endcode
*
* \%^ decodes and prints a data element as formatted XML.
* Requires a pointer to an #OI_DATAELEM.
* @code OI_Printf("Service attribute list is:\n%^", &attributes); @endcode
*
* \%/ prints the base file name of a path, that is, the final substring
* following a '/' or '\\' character. Requires a pointer to a null
* terminated string.
* @code OI_Printf("File %/", "c:\\dir1\\dir2\\file.txt"); @endcode
*
* \%~ prints a string, escaping characters as needed to display it in
* ASCII. Requires a pointer to an #OI_PSTR and an #OI_UNICODE_ENCODING
* parameter.
* @code OI_Printf("Identifier %~", &id, OI_UNICODE_UTF16_BE); @endcode
*
* \%[ inserts an ANSI color escape sequence. Requires a single character
* identifying the color to select. Colors are red (r/R), green (g/G),
* blue (b/B), yellow (y/Y), cyan (c/C), magenta (m/M), white (W),
* light-gray (l/L), dark-gray (d/D), and black (0). The lower case is
* dim, the upper case is bright (except in the case of light-gray and
* dark-gray, where bright and dim are identical). Any other value will
* select the default color.
* @code OI_Printf("%[red text %[black %[normal\n", 'r', '0', 0); @endcode
*
* \%a same as \%s, except '\\r' and '\\n' are output as "<cr>" and "<lf>".
* \%?a is valid, but \%la is not.
*
* \%b prints an integer in base 2.
* @code OI_Printf("Bits are %b", I); @endcode
*
* \%lb prints a long integer in base 2.
*
* \%?b prints the least significant N bits of an integer (or long integer)
* in base 2. Requires the integer and a length N.
* @code OI_Printf("Bottom 4 bits are: %?b", I, 4); @endcode
*
* \%B prints an integer as boolean text, "TRUE" or "FALSE".
* @code OI_Printf("The value 0 is %B, the value 1 is %B", 0, 1); @endcode
*
* \%?s prints a substring up to a specified maximum length.
* Requires a pointer to a string and a length parameter.
* @code OI_Printf("String prefix is %?s", str, 3); @endcode
*
* \%ls same as \%S.
*
* \%S prints a UTF16 string as UTF8 (plain ASCII, plus 8-bit char sequences
* where needed). Requires a pointer to #OI_CHAR16. \%?S is valid. The
* length parameter is in OI_CHAR16 characters.
*
* \%T prints time, formatted as "secs.msecs".
* Requires pointer to #OI_TIME struct, NULL pointer prints current time.
* @code OI_Printf("The time now is %T", NULL); @endcode
*
* @param format The format string
*
*/
void OI_Printf(const OI_CHAR *format, ...);
/**
* Var-args version OI_Printf
*
* @param format Same as for OI_Printf.
*
* @param argp Var-args list.
*/
void OI_VPrintf(const OI_CHAR *format, va_list argp);
/**
* Writes a formatted string to a buffer. This function supports the same format specifiers as
* OI_Printf().
*
* @param buffer Destination buffer for the formatted string.
*
* @param bufLen The length of the destination buffer.
*
* @param format The format string
*
* @return Number of characters written or -1 in the case of an error.
*/
OI_INT32 OI_SNPrintf(OI_CHAR *buffer,
OI_UINT16 bufLen,
const OI_CHAR* format, ...);
/**
* Var-args version OI_SNPrintf
*
* @param buffer Destination buffer for the formatted string.
*
* @param bufLen The length of the destination buffer.
*
* @param format The format string
*
* @param argp Var-args list.
*
* @return Number of characters written or -1 in the case of an error.
*/
OI_INT32 OI_VSNPrintf(OI_CHAR *buffer,
OI_UINT16 bufLen,
const OI_CHAR *format, va_list argp);
/**
* Convert a string to an integer.
*
* @param str the string to parse
*
* @return the integer value of the string or 0 if the string could not be parsed
*/
OI_INT OI_atoi(const OI_CHAR *str);
/**
* Parse a signed integer in a string.
*
* Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string
* must be prefixed by "0x". Returns pointer to first character following the integer. Returns the
* pointer passed in if the string does not describe an integer.
*
* @param str String to parse.
*
* @param val Pointer to receive the parsed integer value.
*
* @return A pointer to the first character following the integer or the pointer passed in.
*/
const OI_CHAR* OI_ScanInt(const OI_CHAR *str,
OI_INT32 *val);
/**
* Parse an unsigned integer in a string.
*
* Skips leading whitespace (space and tabs only) and parses a decimal or hex string. Hex string
* must be prefixed by "0x". Returns pointer to first character following the integer. Returns the
* pointer passed in if the string does not describe an integer.
*
* @param str String to parse.
*
* @param val Pointer to receive the parsed unsigned integer value.
*
* @return A pointer to the first character following the unsigned integer or the pointer passed in.
*/
const OI_CHAR* OI_ScanUInt(const OI_CHAR *str,
OI_UINT32 *val);
/**
* Parse a whitespace delimited substring out of a string.
*
* @param str Input string to parse.
* @param outStr Buffer to return the substring
* @param len Length of outStr
*
*
* @return A pointer to the first character following the substring or the pointer passed in.
*/
const OI_CHAR* OI_ScanStr(const OI_CHAR *str,
OI_CHAR *outStr,
OI_UINT16 len);
/**
* Parse a string for one of a set of alternative value. Skips leading whitespace (space and tabs
* only) and parses text matching one of the alternative strings. Returns pointer to first character
* following the matched text.
*
* @param str String to parse.
*
* @param alts Alternative matching strings separated by '|'
*
* @param index Pointer to receive the index of the matching alternative, return value is -1 if
* there is no match.
*
* @return A pointer to the first character following the matched value or the pointer passed in
* if there was no matching text.
*/
const OI_CHAR* OI_ScanAlt(const OI_CHAR *str,
const OI_CHAR *alts,
OI_INT *index);
/**
* Parse a string for a BD Addr. Skips leading whitespace (space and tabs only) and parses a
* Bluetooth device address with nibbles optionally separated by colons. Return pointet to first
* character following the BD Addr.
*
* @param str String to parse.
*
* @param addr Pointer to receive the Bluetooth device address
*
* @return A pointer to the first character following the BD Addr or the pointer passed in.
*/
const OI_CHAR* OI_ScanBdAddr(const OI_CHAR *str,
OI_BD_ADDR *addr);
/** Get a character from a digit integer value (0 - 9). */
#define OI_DigitToChar(d) ((d) + '0')
/**
* Determine Maximum and Minimum between two arguments.
*
* @param a 1st value
* @param b 2nd value
*
* @return the max or min value between a & b
*/
#define OI_MAX(a, b) (((a) < (b)) ? (b) : (a) )
#define OI_MIN(a, b) (((a) > (b)) ? (b) : (a) )
/**
* Compare two BD_ADDRs
* SAME_BD_ADDR - Boolean: TRUE if they are the same address
*/
#define SAME_BD_ADDR(x, y) (0 == OI_MemCmp((x),(y),OI_BD_ADDR_BYTE_SIZE) )
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* _OI_UTILS_H */
+310 -310
View File
@@ -1,310 +1,310 @@
#include "msbc_decoder_port.h"
static struct sbc_decoder_state sbc_internal_decoder_state = {0};
static void msbc_append_received_data(struct sbc_decoder_state * state, uint8_t * buffer, int size)
{
int numFreeBytes = sizeof(state->frame_buffer) - state->bytes_in_frame_buffer;
if (size > numFreeBytes) {
printf("SBC data: more bytes read %u than free bytes in buffer %u", size, numFreeBytes);
}
(void)memcpy(state->frame_buffer + state->bytes_in_frame_buffer, buffer,
size);
state->bytes_in_frame_buffer += size;
}
// returns position of mSBC sync word
static int msbc_find_h2_sync(const uint8_t *frame_data, OI_UINT32 frame_bytes, int * sync_word_nr)
{
int syncword = mSBC_SYNCWORD;
uint8_t h2_first_byte = 0;
uint8_t h2_second_byte = 0;
unsigned int i;
for (i=0; i<frame_bytes; i++) {
if (frame_data[i] == syncword) {
// check: first byte == 1
if (h2_first_byte == 1) {
// check lower nibble of second byte == 0x08
uint8_t ln = h2_second_byte & 0x0F;
if (ln == 8) {
// check if bits 0+2 == bits 1+3
uint8_t hn = h2_second_byte >> 4;
if ( ((hn>>1) & 0x05) == (hn & 0x05) ) {
*sync_word_nr = ((hn & 0x04) >> 1) | (hn & 0x01);
return i;
}
}
}
}
h2_first_byte = h2_second_byte;
h2_second_byte = frame_data[i];
}
return -1;
}
static int msbc_find_sequence_of_zeros(const uint8_t *frame_data, OI_UINT32 frame_bytes,
int seq_length)
{
int zero_seq_count = 0;
unsigned int i;
for (i=0; i<frame_bytes; i++) {
if (frame_data[i] == 0) {
zero_seq_count++;
if (zero_seq_count >= seq_length)
return zero_seq_count;
} else {
zero_seq_count = 0;
}
}
return 0;
}
static void msbc_decoder_drop_processed_bytes(struct sbc_decoder_state * decoder_state, uint16_t bytes_processed)
{
memmove(decoder_state->frame_buffer, decoder_state->frame_buffer + bytes_processed,
decoder_state->bytes_in_frame_buffer-bytes_processed);
decoder_state->bytes_in_frame_buffer -= bytes_processed;
}
static int16_t msbc_crop_sample(float val){
float croped_val = val;
if (croped_val > 32767.0) croped_val= 32767.0;
if (croped_val < -32768.0) croped_val=-32768.0;
return (int16_t) croped_val;
}
void msbc_plc_good_frame(struct sbc_plc_state *plc_state, int16_t *in, int16_t *out){
float val;
int i = 0;
plc_state->good_frames_nr++;
plc_state->frame_count++;
#ifdef OCTAVE_OUTPUT
FILE * oct_file = NULL;
if (plc_state->nbf>0){
oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_GOOD);
if (oct_file){
octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count);
}
}
#endif
if (plc_state->nbf>0) {
for (i=0;i<SBC_RT;i++) {
out[i] = plc_state->hist[SBC_LHIST+i];
}
for (i = SBC_RT;i<(SBC_RT+SBC_OLAL);i++) {
float left = plc_state->hist[SBC_LHIST+i];
float right = in[i];
val = (left*rcos[i-SBC_RT]) + (right*rcos[SBC_OLAL+SBC_RT-1-i]);
out[i] = msbc_crop_sample(val);
}
}
for (;i<SBC_FS;i++) {
out[i] = in[i];
}
// Copy the output to the history buffer
for (i=0;i<SBC_FS;i++) {
plc_state->hist[SBC_LHIST+i] = out[i];
}
// shift the history buffer
for (i=0;i<SBC_LHIST;i++) {
plc_state->hist[i] = plc_state->hist[i+SBC_FS];
}
#ifdef OCTAVE_OUTPUT
if (oct_file){
octave_fprintf_plot_output(plc_state, oct_file);
fclose(oct_file);
}
#endif
plc_state->nbf=0;
}
static int msbc_decoder_get_num_samples_per_frame(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.nrof_blocks * state->decoder_context.common.frameInfo.nrof_subbands;
}
static int msbc_decoder_get_num_channels(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.nrof_channels;
}
static int msbc_decoder_get_sample_rate(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.frequency;
}
void msbc_decoder_process_msbc_data(int packet_status_flag, uint8_t * buffer, int size)
{
int h2_syncword = 0,h2_sync_pos = 0,zero_seq_found = 0,bytes_missing = 0,bytes_to_append = 0;
int input_bytes = size;
int bad_frame = 0;
uint16_t undecoding_bytes = 0,bytes_processed = 0;
const uint8_t *frame_data;
const unsigned int MSBC_FRAME_SIZE = 60;
struct sbc_decoder_state * decoder_state = &sbc_internal_decoder_state;
while (input_bytes > 0) {
bytes_missing = MSBC_FRAME_SIZE - decoder_state->bytes_in_frame_buffer;
bytes_to_append = (input_bytes < bytes_missing ? input_bytes : bytes_missing);
if (bytes_to_append) {
msbc_append_received_data(decoder_state, buffer, bytes_to_append);
buffer += bytes_to_append;
input_bytes -= bytes_to_append;
}
if (decoder_state->bytes_in_frame_buffer < MSBC_FRAME_SIZE)
break;
undecoding_bytes = decoder_state->bytes_in_frame_buffer;
frame_data = decoder_state->frame_buffer;
// testing only - corrupt frame periodically
//btstack_sbc_decoder_bluedroid_simulate_error(frame_data);
// assert frame looks like this: 01 x8 AD [rest of frame 56 bytes] 00
h2_sync_pos = msbc_find_h2_sync(frame_data, decoder_state->bytes_in_frame_buffer, &h2_syncword);
if (h2_sync_pos < 0) {
// no sync found, discard all but last 2 bytes
bytes_processed = decoder_state->bytes_in_frame_buffer - 2;
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
// don't try PLC without at least a single good frame
if (decoder_state->first_good_frame_found){
decoder_state->msbc_bad_bytes += bytes_processed;
}
continue;
}
zero_seq_found = msbc_find_sequence_of_zeros(frame_data, decoder_state->bytes_in_frame_buffer, 20);
// after first valid frame, zero sequences count as bad frames
if (decoder_state->first_good_frame_found) {
bad_frame = zero_seq_found || packet_status_flag;
}
if (bad_frame) {
// stats
if (zero_seq_found) {
decoder_state->zero_frames_nr++;
} else {
decoder_state->bad_frames_nr++;
}
#ifdef LOG_FRAME_STATUS
if (zero_seq_found) {
printf("%d : ZERO FRAME\n", decoder_state->h2_sequence_nr);
} else {
printf("%d : BAD FRAME\n", decoder_state->h2_sequence_nr);
}
#endif
// retry after dropping 3 byte sync
bytes_processed = 3;
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
decoder_state->msbc_bad_bytes += bytes_processed;
// log_info("Trace bad frame");
continue;
}
//ready to decode frame
OI_STATUS status = OI_CODEC_SBC_DecodeFrame(&(decoder_state->decoder_context),
&frame_data,
&(decoder_state->bytes_in_frame_buffer),
decoder_state->pcm_plc_data,
&(decoder_state->pcm_bytes));
bytes_processed = undecoding_bytes - decoder_state->bytes_in_frame_buffer;
// log_info("Trace decode status %u, processed %u (bad bytes %u), bytes in buffer %u", (int) status, bytes_processed, decoder_state->msbc_bad_bytes, decoder_state->bytes_in_frame_buffer);
switch(status) {
case 0:
// synced
decoder_state->first_good_frame_found = 1;
// get rid of padding byte, not processed by SBC decoder
decoder_state->bytes_in_frame_buffer = 0;
// restart counting bad bytes
decoder_state->msbc_bad_bytes = 0;
// feed good frame into PLC history
msbc_plc_good_frame(&decoder_state->plc_state,
decoder_state->pcm_plc_data,
decoder_state->pcm_data);
// deliver PCM data
decoder_state->handle_pcm_data(decoder_state->pcm_data,
msbc_decoder_get_num_samples_per_frame(decoder_state),
msbc_decoder_get_num_channels(decoder_state),
msbc_decoder_get_sample_rate(decoder_state),
decoder_state->context);
// stats
decoder_state->good_frames_nr++;
continue;
case OI_CODEC_SBC_CHECKSUM_MISMATCH:
// The next frame is somehow corrupt.
printf("OI_CODEC_SBC_CHECKSUM_MISMATCH");
// Did the codec consume any bytes?
if (bytes_processed > 0){
// Good. Nothing to do.
} else {
// Skip the bogus frame by skipping the header.
bytes_processed = 1;
}
break;
case OI_STATUS_INVALID_PARAMETERS:
// This caused by corrupt frames.
// The codec apparently does not recover from this.
// Re-initialize the codec.
printf("SBC decode: invalid parameters: resetting codec");
if (OI_CODEC_mSBC_DecoderReset(&(decoder_state->decoder_context),
decoder_state->decoder_data,
sizeof(decoder_state->decoder_data)) != OI_STATUS_SUCCESS) {
printf("SBC decode: resetting codec failed");
}
break;
default:
printf("Frame decode error: %d", status);
break;
}
// on success, while loop was restarted, so all processed bytes have been "bad"
decoder_state->msbc_bad_bytes += bytes_processed;
// drop processed bytes from frame buffer
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
}
}
int msbc_decoder_init(msbc_decoder_data_cb cb)
{
struct sbc_decoder_state * decoder_state = &sbc_internal_decoder_state;
OI_STATUS status = OI_STATUS_SUCCESS;
status = OI_CODEC_mSBC_DecoderReset(&(decoder_state->decoder_context),
decoder_state->decoder_data,
sizeof(decoder_state->decoder_data));
decoder_state->bytes_in_frame_buffer = 0;
decoder_state->pcm_bytes = sizeof(decoder_state->pcm_data);
decoder_state->h2_sequence_nr = -1;
decoder_state->first_good_frame_found = 0;
decoder_state->handle_pcm_data = cb;
decoder_state->context = NULL;
decoder_state->plc_state.nbf = 0;
decoder_state->plc_state.bestlag = 0;
memset(decoder_state->plc_state.hist,0,sizeof(decoder_state->plc_state.hist));
return (int)status;
}
#include "msbc_decoder_port.h"
static struct sbc_decoder_state sbc_internal_decoder_state = {0};
static void msbc_append_received_data(struct sbc_decoder_state * state, uint8_t * buffer, int size)
{
int numFreeBytes = sizeof(state->frame_buffer) - state->bytes_in_frame_buffer;
if (size > numFreeBytes) {
printf("SBC data: more bytes read %u than free bytes in buffer %u", size, numFreeBytes);
}
(void)memcpy(state->frame_buffer + state->bytes_in_frame_buffer, buffer,
size);
state->bytes_in_frame_buffer += size;
}
// returns position of mSBC sync word
static int msbc_find_h2_sync(const uint8_t *frame_data, OI_UINT32 frame_bytes, int * sync_word_nr)
{
int syncword = mSBC_SYNCWORD;
uint8_t h2_first_byte = 0;
uint8_t h2_second_byte = 0;
unsigned int i;
for (i=0; i<frame_bytes; i++) {
if (frame_data[i] == syncword) {
// check: first byte == 1
if (h2_first_byte == 1) {
// check lower nibble of second byte == 0x08
uint8_t ln = h2_second_byte & 0x0F;
if (ln == 8) {
// check if bits 0+2 == bits 1+3
uint8_t hn = h2_second_byte >> 4;
if ( ((hn>>1) & 0x05) == (hn & 0x05) ) {
*sync_word_nr = ((hn & 0x04) >> 1) | (hn & 0x01);
return i;
}
}
}
}
h2_first_byte = h2_second_byte;
h2_second_byte = frame_data[i];
}
return -1;
}
static int msbc_find_sequence_of_zeros(const uint8_t *frame_data, OI_UINT32 frame_bytes,
int seq_length)
{
int zero_seq_count = 0;
unsigned int i;
for (i=0; i<frame_bytes; i++) {
if (frame_data[i] == 0) {
zero_seq_count++;
if (zero_seq_count >= seq_length)
return zero_seq_count;
} else {
zero_seq_count = 0;
}
}
return 0;
}
static void msbc_decoder_drop_processed_bytes(struct sbc_decoder_state * decoder_state, uint16_t bytes_processed)
{
memmove(decoder_state->frame_buffer, decoder_state->frame_buffer + bytes_processed,
decoder_state->bytes_in_frame_buffer-bytes_processed);
decoder_state->bytes_in_frame_buffer -= bytes_processed;
}
static int16_t msbc_crop_sample(float val){
float croped_val = val;
if (croped_val > 32767.0) croped_val= 32767.0;
if (croped_val < -32768.0) croped_val=-32768.0;
return (int16_t) croped_val;
}
void msbc_plc_good_frame(struct sbc_plc_state *plc_state, int16_t *in, int16_t *out){
float val;
int i = 0;
plc_state->good_frames_nr++;
plc_state->frame_count++;
#ifdef OCTAVE_OUTPUT
FILE * oct_file = NULL;
if (plc_state->nbf>0){
oct_file = open_octave_file(plc_state, OCTAVE_FRAME_TYPE_GOOD);
if (oct_file){
octave_fprintf_plot_history_frame(plc_state, oct_file, plc_state->frame_count);
}
}
#endif
if (plc_state->nbf>0) {
for (i=0;i<SBC_RT;i++) {
out[i] = plc_state->hist[SBC_LHIST+i];
}
for (i = SBC_RT;i<(SBC_RT+SBC_OLAL);i++) {
float left = plc_state->hist[SBC_LHIST+i];
float right = in[i];
val = (left*rcos[i-SBC_RT]) + (right*rcos[SBC_OLAL+SBC_RT-1-i]);
out[i] = msbc_crop_sample(val);
}
}
for (;i<SBC_FS;i++) {
out[i] = in[i];
}
// Copy the output to the history buffer
for (i=0;i<SBC_FS;i++) {
plc_state->hist[SBC_LHIST+i] = out[i];
}
// shift the history buffer
for (i=0;i<SBC_LHIST;i++) {
plc_state->hist[i] = plc_state->hist[i+SBC_FS];
}
#ifdef OCTAVE_OUTPUT
if (oct_file){
octave_fprintf_plot_output(plc_state, oct_file);
fclose(oct_file);
}
#endif
plc_state->nbf=0;
}
static int msbc_decoder_get_num_samples_per_frame(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.nrof_blocks * state->decoder_context.common.frameInfo.nrof_subbands;
}
static int msbc_decoder_get_num_channels(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.nrof_channels;
}
static int msbc_decoder_get_sample_rate(struct sbc_decoder_state * state)
{
return state->decoder_context.common.frameInfo.frequency;
}
void msbc_decoder_process_msbc_data(int packet_status_flag, uint8_t * buffer, int size)
{
int h2_syncword = 0,h2_sync_pos = 0,zero_seq_found = 0,bytes_missing = 0,bytes_to_append = 0;
int input_bytes = size;
int bad_frame = 0;
uint16_t undecoding_bytes = 0,bytes_processed = 0;
const uint8_t *frame_data;
const unsigned int MSBC_FRAME_SIZE = 60;
struct sbc_decoder_state * decoder_state = &sbc_internal_decoder_state;
while (input_bytes > 0) {
bytes_missing = MSBC_FRAME_SIZE - decoder_state->bytes_in_frame_buffer;
bytes_to_append = (input_bytes < bytes_missing ? input_bytes : bytes_missing);
if (bytes_to_append) {
msbc_append_received_data(decoder_state, buffer, bytes_to_append);
buffer += bytes_to_append;
input_bytes -= bytes_to_append;
}
if (decoder_state->bytes_in_frame_buffer < MSBC_FRAME_SIZE)
break;
undecoding_bytes = decoder_state->bytes_in_frame_buffer;
frame_data = decoder_state->frame_buffer;
// testing only - corrupt frame periodically
//btstack_sbc_decoder_bluedroid_simulate_error(frame_data);
// assert frame looks like this: 01 x8 AD [rest of frame 56 bytes] 00
h2_sync_pos = msbc_find_h2_sync(frame_data, decoder_state->bytes_in_frame_buffer, &h2_syncword);
if (h2_sync_pos < 0) {
// no sync found, discard all but last 2 bytes
bytes_processed = decoder_state->bytes_in_frame_buffer - 2;
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
// don't try PLC without at least a single good frame
if (decoder_state->first_good_frame_found){
decoder_state->msbc_bad_bytes += bytes_processed;
}
continue;
}
zero_seq_found = msbc_find_sequence_of_zeros(frame_data, decoder_state->bytes_in_frame_buffer, 20);
// after first valid frame, zero sequences count as bad frames
if (decoder_state->first_good_frame_found) {
bad_frame = zero_seq_found || packet_status_flag;
}
if (bad_frame) {
// stats
if (zero_seq_found) {
decoder_state->zero_frames_nr++;
} else {
decoder_state->bad_frames_nr++;
}
#ifdef LOG_FRAME_STATUS
if (zero_seq_found) {
printf("%d : ZERO FRAME\n", decoder_state->h2_sequence_nr);
} else {
printf("%d : BAD FRAME\n", decoder_state->h2_sequence_nr);
}
#endif
// retry after dropping 3 byte sync
bytes_processed = 3;
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
decoder_state->msbc_bad_bytes += bytes_processed;
// log_info("Trace bad frame");
continue;
}
//ready to decode frame
OI_STATUS status = OI_CODEC_SBC_DecodeFrame(&(decoder_state->decoder_context),
&frame_data,
&(decoder_state->bytes_in_frame_buffer),
decoder_state->pcm_plc_data,
&(decoder_state->pcm_bytes));
bytes_processed = undecoding_bytes - decoder_state->bytes_in_frame_buffer;
// log_info("Trace decode status %u, processed %u (bad bytes %u), bytes in buffer %u", (int) status, bytes_processed, decoder_state->msbc_bad_bytes, decoder_state->bytes_in_frame_buffer);
switch(status) {
case 0:
// synced
decoder_state->first_good_frame_found = 1;
// get rid of padding byte, not processed by SBC decoder
decoder_state->bytes_in_frame_buffer = 0;
// restart counting bad bytes
decoder_state->msbc_bad_bytes = 0;
// feed good frame into PLC history
msbc_plc_good_frame(&decoder_state->plc_state,
decoder_state->pcm_plc_data,
decoder_state->pcm_data);
// deliver PCM data
decoder_state->handle_pcm_data(decoder_state->pcm_data,
msbc_decoder_get_num_samples_per_frame(decoder_state),
msbc_decoder_get_num_channels(decoder_state),
msbc_decoder_get_sample_rate(decoder_state),
decoder_state->context);
// stats
decoder_state->good_frames_nr++;
continue;
case OI_CODEC_SBC_CHECKSUM_MISMATCH:
// The next frame is somehow corrupt.
printf("OI_CODEC_SBC_CHECKSUM_MISMATCH");
// Did the codec consume any bytes?
if (bytes_processed > 0){
// Good. Nothing to do.
} else {
// Skip the bogus frame by skipping the header.
bytes_processed = 1;
}
break;
case OI_STATUS_INVALID_PARAMETERS:
// This caused by corrupt frames.
// The codec apparently does not recover from this.
// Re-initialize the codec.
printf("SBC decode: invalid parameters: resetting codec");
if (OI_CODEC_mSBC_DecoderReset(&(decoder_state->decoder_context),
decoder_state->decoder_data,
sizeof(decoder_state->decoder_data)) != OI_STATUS_SUCCESS) {
printf("SBC decode: resetting codec failed");
}
break;
default:
printf("Frame decode error: %d", status);
break;
}
// on success, while loop was restarted, so all processed bytes have been "bad"
decoder_state->msbc_bad_bytes += bytes_processed;
// drop processed bytes from frame buffer
msbc_decoder_drop_processed_bytes(decoder_state, bytes_processed);
}
}
int msbc_decoder_init(msbc_decoder_data_cb cb)
{
struct sbc_decoder_state * decoder_state = &sbc_internal_decoder_state;
OI_STATUS status = OI_STATUS_SUCCESS;
status = OI_CODEC_mSBC_DecoderReset(&(decoder_state->decoder_context),
decoder_state->decoder_data,
sizeof(decoder_state->decoder_data));
decoder_state->bytes_in_frame_buffer = 0;
decoder_state->pcm_bytes = sizeof(decoder_state->pcm_data);
decoder_state->h2_sequence_nr = -1;
decoder_state->first_good_frame_found = 0;
decoder_state->handle_pcm_data = cb;
decoder_state->context = NULL;
decoder_state->plc_state.nbf = 0;
decoder_state->plc_state.bestlag = 0;
memset(decoder_state->plc_state.hist,0,sizeof(decoder_state->plc_state.hist));
return (int)status;
}
+70 -70
View File
@@ -1,70 +1,70 @@
#ifndef __MSBC_DECODER_PORT_H_
#define __MSBC_DECODER_PORT_H_
#include "oi_codec_sbc.h"
#include <stdint.h>
#define DECODER_DATA_SIZE (SBC_MAX_CHANNELS*SBC_MAX_BLOCKS*SBC_MAX_BANDS * 4 + \
SBC_CODEC_MIN_FILTER_BUFFERS*SBC_MAX_BANDS*SBC_MAX_CHANNELS * 2)
#define SBC_FS 120 /* SBC Frame Size */
#define SBC_N 512 /* 32ms - Window Length for pattern matching */
#define SBC_M 64 /* 4ms - Template for matching */
#define SBC_LHIST (SBC_N+SBC_FS-1) /* Length of history buffer required */
#define SBC_RT 36 /* SBC Reconvergence Time (samples) */
#define SBC_OLAL 16 /* OverLap-Add Length (samples) */
#define mSBC_SYNCWORD 0xad
static float rcos[8] = {
0.99148655f,0.92510857f,
0.80131732f,0.63683150f,
0.45386582f,0.27713082f,
0.13049554f,0.03376389f,
};
/* PLC State Information */
struct sbc_plc_state {
int16_t hist[SBC_LHIST+SBC_FS+SBC_RT+SBC_OLAL];
int16_t bestlag;
int nbf;
// summary of processed good and bad frames
int good_frames_nr;
int bad_frames_nr;
int frame_count;
int max_consecutive_bad_frames_nr;
} __attribute__((packed));
struct sbc_decoder_state {
void *context;
struct sbc_plc_state plc_state;
void (*handle_pcm_data)(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context);
uint32_t bytes_in_frame_buffer;
OI_CODEC_SBC_DECODER_CONTEXT decoder_context;
uint8_t frame_buffer[SBC_MAX_FRAME_LEN];
int16_t pcm_plc_data[SBC_MAX_CHANNELS * SBC_MAX_BANDS * SBC_MAX_BLOCKS];
int16_t pcm_data[SBC_MAX_CHANNELS * SBC_MAX_BANDS * SBC_MAX_BLOCKS];
uint32_t pcm_bytes;
uint32_t decoder_data[(DECODER_DATA_SIZE+3)/4];
int first_good_frame_found;
int h2_sequence_nr;
uint16_t msbc_bad_bytes;
// summary of processed good, bad and zero frames
int good_frames_nr;
int bad_frames_nr;
int zero_frames_nr;
};
typedef void (*msbc_decoder_data_cb)(int16_t * data, int num_samples,int num_channels,
int sample_rate, void * context);
void msbc_decoder_process_msbc_data(int packet_status_flag, uint8_t * buffer, int size);
int msbc_decoder_init(msbc_decoder_data_cb cb);
#endif
#ifndef __MSBC_DECODER_PORT_H_
#define __MSBC_DECODER_PORT_H_
#include "oi_codec_sbc.h"
#include <stdint.h>
#define DECODER_DATA_SIZE (SBC_MAX_CHANNELS*SBC_MAX_BLOCKS*SBC_MAX_BANDS * 4 + \
SBC_CODEC_MIN_FILTER_BUFFERS*SBC_MAX_BANDS*SBC_MAX_CHANNELS * 2)
#define SBC_FS 120 /* SBC Frame Size */
#define SBC_N 512 /* 32ms - Window Length for pattern matching */
#define SBC_M 64 /* 4ms - Template for matching */
#define SBC_LHIST (SBC_N+SBC_FS-1) /* Length of history buffer required */
#define SBC_RT 36 /* SBC Reconvergence Time (samples) */
#define SBC_OLAL 16 /* OverLap-Add Length (samples) */
#define mSBC_SYNCWORD 0xad
static float rcos[8] = {
0.99148655f,0.92510857f,
0.80131732f,0.63683150f,
0.45386582f,0.27713082f,
0.13049554f,0.03376389f,
};
/* PLC State Information */
struct sbc_plc_state {
int16_t hist[SBC_LHIST+SBC_FS+SBC_RT+SBC_OLAL];
int16_t bestlag;
int nbf;
// summary of processed good and bad frames
int good_frames_nr;
int bad_frames_nr;
int frame_count;
int max_consecutive_bad_frames_nr;
} __attribute__((packed));
struct sbc_decoder_state {
void *context;
struct sbc_plc_state plc_state;
void (*handle_pcm_data)(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context);
uint32_t bytes_in_frame_buffer;
OI_CODEC_SBC_DECODER_CONTEXT decoder_context;
uint8_t frame_buffer[SBC_MAX_FRAME_LEN];
int16_t pcm_plc_data[SBC_MAX_CHANNELS * SBC_MAX_BANDS * SBC_MAX_BLOCKS];
int16_t pcm_data[SBC_MAX_CHANNELS * SBC_MAX_BANDS * SBC_MAX_BLOCKS];
uint32_t pcm_bytes;
uint32_t decoder_data[(DECODER_DATA_SIZE+3)/4];
int first_good_frame_found;
int h2_sequence_nr;
uint16_t msbc_bad_bytes;
// summary of processed good, bad and zero frames
int good_frames_nr;
int bad_frames_nr;
int zero_frames_nr;
};
typedef void (*msbc_decoder_data_cb)(int16_t * data, int num_samples,int num_channels,
int sample_rate, void * context);
void msbc_decoder_process_msbc_data(int packet_status_flag, uint8_t * buffer, int size);
int msbc_decoder_init(msbc_decoder_data_cb cb);
#endif
+78 -78
View File
@@ -1,78 +1,78 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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 <stdlib.h>
#include <oi_codec_sbc_private.h>
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT32 *codecDataAligned,
OI_UINT32 codecDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride)
{
int i;
size_t filterBufferCount;
size_t subdataSize;
OI_BYTE *codecData = (OI_BYTE*)codecDataAligned;
if ((maxChannels < 1) || (maxChannels > 2)) {
return OI_STATUS_INVALID_PARAMETERS;
}
if ((pcmStride < 1) || (pcmStride > maxChannels)) {
return OI_STATUS_INVALID_PARAMETERS;
}
common->maxChannels = maxChannels;
common->pcmStride = pcmStride;
/* Compute sizes needed for the memory regions, and bail if we don't have
* enough memory for them. */
subdataSize = maxChannels * sizeof(common->subdata[0]) * SBC_MAX_BANDS * SBC_MAX_BLOCKS;
if (subdataSize > codecDataBytes) {
return OI_STATUS_OUT_OF_MEMORY;
}
filterBufferCount = (codecDataBytes - subdataSize) / (sizeof(common->filterBuffer[0][0]) * SBC_MAX_BANDS * maxChannels);
if (filterBufferCount < SBC_CODEC_MIN_FILTER_BUFFERS) {
return OI_STATUS_OUT_OF_MEMORY;
}
common->filterBufferLen = (uint32_t) filterBufferCount * SBC_MAX_BANDS;
/* Allocate memory for the subband data */
common->subdata = (OI_INT32*)codecData;
codecData += subdataSize;
OI_ASSERT(codecDataBytes >= subdataSize);
codecDataBytes -= (uint32_t) subdataSize;
/* Allocate memory for the synthesis buffers */
for (i = 0; i < maxChannels; ++i) {
size_t allocSize = common->filterBufferLen * sizeof(common->filterBuffer[0][0]);
common->filterBuffer[i] = (SBC_BUFFER_T*)codecData;
OI_ASSERT(codecDataBytes >= allocSize);
codecData += allocSize;
codecDataBytes -= (uint32_t) allocSize;
}
return OI_OK;
}
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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 <stdlib.h>
#include <oi_codec_sbc_private.h>
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT32 *codecDataAligned,
OI_UINT32 codecDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride)
{
int i;
size_t filterBufferCount;
size_t subdataSize;
OI_BYTE *codecData = (OI_BYTE*)codecDataAligned;
if ((maxChannels < 1) || (maxChannels > 2)) {
return OI_STATUS_INVALID_PARAMETERS;
}
if ((pcmStride < 1) || (pcmStride > maxChannels)) {
return OI_STATUS_INVALID_PARAMETERS;
}
common->maxChannels = maxChannels;
common->pcmStride = pcmStride;
/* Compute sizes needed for the memory regions, and bail if we don't have
* enough memory for them. */
subdataSize = maxChannels * sizeof(common->subdata[0]) * SBC_MAX_BANDS * SBC_MAX_BLOCKS;
if (subdataSize > codecDataBytes) {
return OI_STATUS_OUT_OF_MEMORY;
}
filterBufferCount = (codecDataBytes - subdataSize) / (sizeof(common->filterBuffer[0][0]) * SBC_MAX_BANDS * maxChannels);
if (filterBufferCount < SBC_CODEC_MIN_FILTER_BUFFERS) {
return OI_STATUS_OUT_OF_MEMORY;
}
common->filterBufferLen = (uint32_t) filterBufferCount * SBC_MAX_BANDS;
/* Allocate memory for the subband data */
common->subdata = (OI_INT32*)codecData;
codecData += subdataSize;
OI_ASSERT(codecDataBytes >= subdataSize);
codecDataBytes -= (uint32_t) subdataSize;
/* Allocate memory for the synthesis buffers */
for (i = 0; i < maxChannels; ++i) {
size_t allocSize = common->filterBufferLen * sizeof(common->filterBuffer[0][0]);
common->filterBuffer[i] = (SBC_BUFFER_T*)codecData;
OI_ASSERT(codecDataBytes >= allocSize);
codecData += allocSize;
codecDataBytes -= (uint32_t) allocSize;
}
return OI_OK;
}
+165 -165
View File
@@ -1,165 +1,165 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
#include <oi_codec_sbc_private.h>
static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_UINT bitcountL;
OI_UINT bitcountR;
OI_UINT bitpoolPreferenceL = 0;
OI_UINT bitpoolPreferenceR = 0;
BITNEED_UNION1 bitneedsL;
BITNEED_UNION1 bitneedsR;
bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
}
static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
BITNEED_UNION2 bitneeds;
OI_UINT excess;
OI_INT bitadjust;
OI_UINT bitcount;
OI_UINT sbL;
OI_UINT sbR;
OI_UINT bitpoolPreference = 0;
bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
{
OI_UINT ex;
bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
/* We want the compiler to put excess into a register */
excess = ex;
}
sbL = 0;
sbR = nrof_subbands;
while (sbL < nrof_subbands) {
excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
++sbL;
excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
++sbR;
}
sbL = 0;
sbR = nrof_subbands;
while (excess) {
excess = allocExcessBits(&common->bits.uint8[sbL], excess);
++sbL;
if (!excess) {
break;
}
excess = allocExcessBits(&common->bits.uint8[sbR], excess);
++sbR;
}
}
static const BIT_ALLOC balloc[] = {
monoBitAllocation, /* SBC_MONO */
dualBitAllocation, /* SBC_DUAL_CHANNEL */
stereoBitAllocation, /* SBC_STEREO */
stereoBitAllocation /* SBC_JOINT_STEREO */
};
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
/*
* Using an array of function pointers prevents the compiler from creating a suboptimal
* monolithic inlined bit allocation function.
*/
balloc[common->frameInfo.mode](common);
}
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
{
return internal_CalculateBitrate(frame);
}
/*
* Return the current maximum bitneed and clear it.
*/
#if 0
OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_UINT8 max = common->maxBitneed;
common->maxBitneed = 0;
return max;
}
#endif
/*
* Calculates the bitpool size for a given frame length
*/
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
OI_UINT16 frameLen)
{
OI_UINT16 nrof_subbands = frame->nrof_subbands;
OI_UINT16 nrof_blocks = frame->nrof_blocks;
OI_UINT16 hdr;
OI_UINT16 bits;
if (frame->mode == SBC_JOINT_STEREO) {
hdr = 9 * nrof_subbands;
} else {
if (frame->mode == SBC_MONO) {
hdr = 4 * nrof_subbands;
} else {
hdr = 8 * nrof_subbands;
}
if (frame->mode == SBC_DUAL_CHANNEL) {
nrof_blocks *= 2;
}
}
bits = (8 * (frameLen - SBC_HEADER_LEN)) - hdr;
return DIVIDE(bits, nrof_blocks);
}
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
}
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
{
return internal_CalculateFramelen(frame);
}
/**@}*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
#include <oi_codec_sbc_private.h>
static void dualBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_UINT bitcountL;
OI_UINT bitcountR;
OI_UINT bitpoolPreferenceL = 0;
OI_UINT bitpoolPreferenceR = 0;
BITNEED_UNION1 bitneedsL;
BITNEED_UNION1 bitneedsR;
bitcountL = computeBitneed(common, bitneedsL.uint8, 0, &bitpoolPreferenceL);
bitcountR = computeBitneed(common, bitneedsR.uint8, 1, &bitpoolPreferenceR);
oneChannelBitAllocation(common, &bitneedsL, 0, bitcountL);
oneChannelBitAllocation(common, &bitneedsR, 1, bitcountR);
}
static void stereoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
BITNEED_UNION2 bitneeds;
OI_UINT excess;
OI_INT bitadjust;
OI_UINT bitcount;
OI_UINT sbL;
OI_UINT sbR;
OI_UINT bitpoolPreference = 0;
bitcount = computeBitneed(common, &bitneeds.uint8[0], 0, &bitpoolPreference);
bitcount += computeBitneed(common, &bitneeds.uint8[nrof_subbands], 1, &bitpoolPreference);
{
OI_UINT ex;
bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds.uint32, 2 * nrof_subbands, bitcount, &ex);
/* We want the compiler to put excess into a register */
excess = ex;
}
sbL = 0;
sbR = nrof_subbands;
while (sbL < nrof_subbands) {
excess = allocAdjustedBits(&common->bits.uint8[sbL], bitneeds.uint8[sbL] + bitadjust, excess);
++sbL;
excess = allocAdjustedBits(&common->bits.uint8[sbR], bitneeds.uint8[sbR] + bitadjust, excess);
++sbR;
}
sbL = 0;
sbR = nrof_subbands;
while (excess) {
excess = allocExcessBits(&common->bits.uint8[sbL], excess);
++sbL;
if (!excess) {
break;
}
excess = allocExcessBits(&common->bits.uint8[sbR], excess);
++sbR;
}
}
static const BIT_ALLOC balloc[] = {
monoBitAllocation, /* SBC_MONO */
dualBitAllocation, /* SBC_DUAL_CHANNEL */
stereoBitAllocation, /* SBC_STEREO */
stereoBitAllocation /* SBC_JOINT_STEREO */
};
PRIVATE void OI_SBC_ComputeBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_ASSERT(common->frameInfo.bitpool <= OI_SBC_MaxBitpool(&common->frameInfo));
OI_ASSERT(common->frameInfo.mode < OI_ARRAYSIZE(balloc));
/*
* Using an array of function pointers prevents the compiler from creating a suboptimal
* monolithic inlined bit allocation function.
*/
balloc[common->frameInfo.mode](common);
}
OI_UINT32 OI_CODEC_SBC_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
{
return internal_CalculateBitrate(frame);
}
/*
* Return the current maximum bitneed and clear it.
*/
#if 0
OI_UINT8 OI_CODEC_SBC_GetMaxBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
OI_UINT8 max = common->maxBitneed;
common->maxBitneed = 0;
return max;
}
#endif
/*
* Calculates the bitpool size for a given frame length
*/
OI_UINT16 OI_CODEC_SBC_CalculateBitpool(OI_CODEC_SBC_FRAME_INFO *frame,
OI_UINT16 frameLen)
{
OI_UINT16 nrof_subbands = frame->nrof_subbands;
OI_UINT16 nrof_blocks = frame->nrof_blocks;
OI_UINT16 hdr;
OI_UINT16 bits;
if (frame->mode == SBC_JOINT_STEREO) {
hdr = 9 * nrof_subbands;
} else {
if (frame->mode == SBC_MONO) {
hdr = 4 * nrof_subbands;
} else {
hdr = 8 * nrof_subbands;
}
if (frame->mode == SBC_DUAL_CHANNEL) {
nrof_blocks *= 2;
}
}
bits = (8 * (frameLen - SBC_HEADER_LEN)) - hdr;
return DIVIDE(bits, nrof_blocks);
}
OI_UINT16 OI_CODEC_SBC_CalculatePcmBytes(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
return sizeof(OI_INT16) * common->pcmStride * common->frameInfo.nrof_subbands * common->frameInfo.nrof_blocks;
}
OI_UINT16 OI_CODEC_SBC_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
{
return internal_CalculateFramelen(frame);
}
/**@}*/
+394 -394
View File
@@ -1,394 +1,394 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
The functions in this file relate to the allocation of available bits to
subbands within the SBC/eSBC frame, along with support functions for computing
frame length and bitrate.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_utils.h"
#include <oi_codec_sbc_private.h>
OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame)
{
switch (frame->mode) {
case SBC_MONO:
case SBC_DUAL_CHANNEL:
return 16 * frame->nrof_subbands;
case SBC_STEREO:
case SBC_JOINT_STEREO:
return 32 * frame->nrof_subbands;
default:
break;
}
ERROR(("Invalid frame mode %d", frame->mode));
OI_ASSERT(FALSE);
return 0; /* Should never be reached */
}
PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
{
OI_UINT16 nbits = frame->nrof_blocks * frame->bitpool;
OI_UINT16 nrof_subbands = frame->nrof_subbands;
OI_UINT16 result = nbits;
if (frame->mode == SBC_JOINT_STEREO) {
result += nrof_subbands + (8 * nrof_subbands);
} else {
if (frame->mode == SBC_DUAL_CHANNEL) { result += nbits; }
if (frame->mode == SBC_MONO) { result += 4*nrof_subbands; } else { result += 8*nrof_subbands; }
}
return SBC_HEADER_LEN + ((result + 7) / 8);
}
PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
{
OI_UINT blocksbands;
blocksbands = frame->nrof_subbands * frame->nrof_blocks;
return DIVIDE(8 * internal_CalculateFramelen(frame) * frame->frequency, blocksbands);
}
INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_)
{
OI_UINT headerLen = SBC_HEADER_LEN + (frame->nrof_subbands * frame->nrof_channels/2);
if (frame->mode == SBC_JOINT_STEREO) { headerLen++; }
*headerLen_ = headerLen;
return internal_CalculateFramelen(frame);
}
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/*
* Computes the bit need for each sample and as also returns a counts of bit needs that are greater
* than one. This count is used in the first phase of bit allocation.
*
* We also compute a preferred bitpool value that this is the minimum bitpool needed to guarantee
* lossless representation of the audio data. The preferred bitpool may be larger than the bits
* actually required but the only input we have are the scale factors. For example, it takes 2 bits
* to represent values in the range -1 .. +1 but the scale factor is 0. To guarantee lossless
* representation we add 2 to each scale factor and sum them to come up with the preferred bitpool.
* This is not ideal because 0 requires 0 bits but we currently have no way of knowing this.
*
* @param bitneed Array to return bitneeds for each subband
*
* @param ch Channel 0 or 1
*
* @param preferredBitpool Returns the number of reserved bits
*
* @return The SBC bit need
*
*/
OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT8 *bitneeds,
OI_UINT ch,
OI_UINT *preferredBitpool)
{
static const OI_INT8 offset4[4][4] = {
{ -1, 0, 0, 0 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 }
};
static const OI_INT8 offset8[4][8] = {
{ -2, 0, 0, 0, 0, 0, 0, 1 },
{ -3, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 }
};
const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
OI_UINT sb;
OI_INT8 *scale_factor = &common->scale_factor[ch ? nrof_subbands : 0];
OI_UINT bitcount = 0;
OI_UINT8 maxBits = 0;
OI_UINT8 prefBits = 0;
if (common->frameInfo.alloc == SBC_SNR) {
for (sb = 0; sb < nrof_subbands; sb++) {
OI_INT bits = scale_factor[sb];
if (bits > maxBits) {
maxBits = bits;
}
if ((bitneeds[sb] = bits) > 1) {
bitcount += bits;
}
prefBits += 2 + bits;
}
} else {
const OI_INT8 *offset;
if (nrof_subbands == 4) {
offset = offset4[common->frameInfo.freqIndex];
} else {
offset = offset8[common->frameInfo.freqIndex];
}
for (sb = 0; sb < nrof_subbands; sb++) {
OI_INT bits = scale_factor[sb];
if (bits > maxBits) {
maxBits = bits;
}
prefBits += 2 + bits;
if (bits) {
bits -= offset[sb];
if (bits > 0) {
bits /= 2;
}
bits += 5;
}
if ((bitneeds[sb] = bits) > 1) {
bitcount += bits;
}
}
}
common->maxBitneed = OI_MAX(maxBits, common->maxBitneed);
*preferredBitpool += prefBits;
return bitcount;
}
/*
* Explanation of the adjustToFitBitpool inner loop.
*
* The inner loop computes the effect of adjusting the bit allocation up or
* down. Allocations must be 0 or in the range 2..16. This is accomplished by
* the following code:
*
* for (s = bands - 1; s >= 0; --s) {
* OI_INT bits = bitadjust + bitneeds[s];
* bits = bits < 2 ? 0 : bits;
* bits = bits > 16 ? 16 : bits;
* count += bits;
* }
*
* This loop can be optimized to perform 4 operations at a time as follows:
*
* Adjustment is computed as a 7 bit signed value and added to the bitneed.
*
* Negative allocations are zeroed by masking. (n & 0x40) >> 6 puts the
* sign bit into bit 0, adding this to 0x7F give us a mask of 0x80
* for -ve values and 0x7F for +ve values.
*
* n &= 0x7F + (n & 0x40) >> 6)
*
* Allocations greater than 16 are truncated to 16. Adjusted allocations are in
* the range 0..31 so we know that bit 4 indicates values >= 16. We use this bit
* to create a mask that zeroes bits 0 .. 3 if bit 4 is set.
*
* n &= (15 + (n >> 4))
*
* Allocations of 1 are disallowed. Add and shift creates a mask that
* eliminates the illegal value
*
* n &= ((n + 14) >> 4) | 0x1E
*
* These operations can be performed in 8 bits without overflowing so we can
* operate on 4 values at once.
*/
/*
* Encoder/Decoder
*
* Computes adjustment +/- of bitneeds to fill bitpool and returns overall
* adjustment and excess bits.
*
* @param bitpool The bitpool we have to work within
*
* @param bitneeds An array of bit needs (more acturately allocation prioritities) for each
* subband across all blocks in the SBC frame
*
* @param subbands The number of subbands over which the adkustment is calculated. For mono and
* dual mode this is 4 or 8, for stereo or joint stereo this is 8 or 16.
*
* @param bitcount A starting point for the adjustment
*
* @param excess Returns the excess bits after the adjustment
*
* @return The adjustment.
*/
OI_INT adjustToFitBitpool(const OI_UINT bitpool,
OI_UINT32 *bitneeds,
const OI_UINT subbands,
OI_UINT bitcount,
OI_UINT *excess)
{
OI_INT maxBitadjust = 0;
OI_INT bitadjust = (bitcount > bitpool) ? -8 : 8;
OI_INT chop = 8;
/*
* This is essentially a binary search for the optimal adjustment value.
*/
while ((bitcount != bitpool) && chop) {
OI_UINT32 total = 0;
OI_UINT count;
OI_UINT32 adjust4;
OI_INT i;
adjust4 = bitadjust & 0x7F;
adjust4 |= (adjust4 << 8);
adjust4 |= (adjust4 << 16);
for (i = ((subbands / 4) - 1); i >= 0; --i) {
OI_UINT32 mask;
OI_UINT32 n = bitneeds[i] + adjust4;
mask = 0x7F7F7F7F + ((n & 0x40404040) >> 6);
n &= mask;
mask = 0x0F0F0F0F + ((n & 0x10101010) >> 4);
n &= mask;
mask = (((n + 0x0E0E0E0E) >> 4) | 0x1E1E1E1E);
n &= mask;
total += n;
}
count = (total & 0xFFFF) + (total >> 16);
count = (count & 0xFF) + (count >> 8);
chop >>= 1;
if (count > bitpool) {
bitadjust -= chop;
} else {
maxBitadjust = bitadjust;
bitcount = count;
bitadjust += chop;
}
}
*excess = bitpool - bitcount;
return maxBitadjust;
}
/*
* The bit allocator trys to avoid single bit allocations except as a last resort. So in the case
* where a bitneed of 1 was passed over during the adsjustment phase 2 bits are now allocated.
*/
INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest,
OI_INT bits,
OI_INT excess)
{
if (bits < 16) {
if (bits > 1) {
if (excess) {
++bits;
--excess;
}
} else if ((bits == 1) && (excess > 1)) {
bits = 2;
excess -= 2;
} else {
bits = 0;
}
} else {
bits = 16;
}
*dest = (OI_UINT8)bits;
return excess;
}
/*
* Excess bits not allocated by allocaAdjustedBits are allocated round-robin.
*/
INLINE OI_INT allocExcessBits(OI_UINT8 *dest,
OI_INT excess)
{
if (*dest < 16) {
*dest += 1;
return excess - 1;
} else {
return excess;
}
}
void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common,
BITNEED_UNION1 *bitneeds,
OI_UINT ch,
OI_UINT bitcount)
{
const OI_UINT8 nrof_subbands = common->frameInfo.nrof_subbands;
OI_UINT excess;
OI_UINT sb;
OI_INT bitadjust;
OI_UINT8 RESTRICT *allocBits;
{
OI_UINT ex;
bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds->uint32, nrof_subbands, bitcount, &ex);
/* We want the compiler to put excess into a register */
excess = ex;
}
/*
* Allocate adjusted bits
*/
allocBits = &common->bits.uint8[ch ? nrof_subbands : 0];
sb = 0;
while (sb < nrof_subbands) {
excess = allocAdjustedBits(&allocBits[sb], bitneeds->uint8[sb] + bitadjust, excess);
++sb;
}
sb = 0;
while (excess) {
excess = allocExcessBits(&allocBits[sb], excess);
++sb;
}
}
void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
BITNEED_UNION1 bitneeds;
OI_UINT bitcount;
OI_UINT bitpoolPreference = 0;
bitcount = computeBitneed(common, bitneeds.uint8, 0, &bitpoolPreference);
oneChannelBitAllocation(common, &bitneeds, 0, bitcount);
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
The functions in this file relate to the allocation of available bits to
subbands within the SBC/eSBC frame, along with support functions for computing
frame length and bitrate.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_utils.h"
#include <oi_codec_sbc_private.h>
OI_UINT32 OI_SBC_MaxBitpool(OI_CODEC_SBC_FRAME_INFO *frame)
{
switch (frame->mode) {
case SBC_MONO:
case SBC_DUAL_CHANNEL:
return 16 * frame->nrof_subbands;
case SBC_STEREO:
case SBC_JOINT_STEREO:
return 32 * frame->nrof_subbands;
default:
break;
}
ERROR(("Invalid frame mode %d", frame->mode));
OI_ASSERT(FALSE);
return 0; /* Should never be reached */
}
PRIVATE OI_UINT16 internal_CalculateFramelen(OI_CODEC_SBC_FRAME_INFO *frame)
{
OI_UINT16 nbits = frame->nrof_blocks * frame->bitpool;
OI_UINT16 nrof_subbands = frame->nrof_subbands;
OI_UINT16 result = nbits;
if (frame->mode == SBC_JOINT_STEREO) {
result += nrof_subbands + (8 * nrof_subbands);
} else {
if (frame->mode == SBC_DUAL_CHANNEL) { result += nbits; }
if (frame->mode == SBC_MONO) { result += 4*nrof_subbands; } else { result += 8*nrof_subbands; }
}
return SBC_HEADER_LEN + ((result + 7) / 8);
}
PRIVATE OI_UINT32 internal_CalculateBitrate(OI_CODEC_SBC_FRAME_INFO *frame)
{
OI_UINT blocksbands;
blocksbands = frame->nrof_subbands * frame->nrof_blocks;
return DIVIDE(8 * internal_CalculateFramelen(frame) * frame->frequency, blocksbands);
}
INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_)
{
OI_UINT headerLen = SBC_HEADER_LEN + (frame->nrof_subbands * frame->nrof_channels/2);
if (frame->mode == SBC_JOINT_STEREO) { headerLen++; }
*headerLen_ = headerLen;
return internal_CalculateFramelen(frame);
}
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/*
* Computes the bit need for each sample and as also returns a counts of bit needs that are greater
* than one. This count is used in the first phase of bit allocation.
*
* We also compute a preferred bitpool value that this is the minimum bitpool needed to guarantee
* lossless representation of the audio data. The preferred bitpool may be larger than the bits
* actually required but the only input we have are the scale factors. For example, it takes 2 bits
* to represent values in the range -1 .. +1 but the scale factor is 0. To guarantee lossless
* representation we add 2 to each scale factor and sum them to come up with the preferred bitpool.
* This is not ideal because 0 requires 0 bits but we currently have no way of knowing this.
*
* @param bitneed Array to return bitneeds for each subband
*
* @param ch Channel 0 or 1
*
* @param preferredBitpool Returns the number of reserved bits
*
* @return The SBC bit need
*
*/
OI_UINT computeBitneed(OI_CODEC_SBC_COMMON_CONTEXT *common,
OI_UINT8 *bitneeds,
OI_UINT ch,
OI_UINT *preferredBitpool)
{
static const OI_INT8 offset4[4][4] = {
{ -1, 0, 0, 0 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 },
{ -2, 0, 0, 1 }
};
static const OI_INT8 offset8[4][8] = {
{ -2, 0, 0, 0, 0, 0, 0, 1 },
{ -3, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 },
{ -4, 0, 0, 0, 0, 0, 1, 2 }
};
const OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
OI_UINT sb;
OI_INT8 *scale_factor = &common->scale_factor[ch ? nrof_subbands : 0];
OI_UINT bitcount = 0;
OI_UINT8 maxBits = 0;
OI_UINT8 prefBits = 0;
if (common->frameInfo.alloc == SBC_SNR) {
for (sb = 0; sb < nrof_subbands; sb++) {
OI_INT bits = scale_factor[sb];
if (bits > maxBits) {
maxBits = bits;
}
if ((bitneeds[sb] = bits) > 1) {
bitcount += bits;
}
prefBits += 2 + bits;
}
} else {
const OI_INT8 *offset;
if (nrof_subbands == 4) {
offset = offset4[common->frameInfo.freqIndex];
} else {
offset = offset8[common->frameInfo.freqIndex];
}
for (sb = 0; sb < nrof_subbands; sb++) {
OI_INT bits = scale_factor[sb];
if (bits > maxBits) {
maxBits = bits;
}
prefBits += 2 + bits;
if (bits) {
bits -= offset[sb];
if (bits > 0) {
bits /= 2;
}
bits += 5;
}
if ((bitneeds[sb] = bits) > 1) {
bitcount += bits;
}
}
}
common->maxBitneed = OI_MAX(maxBits, common->maxBitneed);
*preferredBitpool += prefBits;
return bitcount;
}
/*
* Explanation of the adjustToFitBitpool inner loop.
*
* The inner loop computes the effect of adjusting the bit allocation up or
* down. Allocations must be 0 or in the range 2..16. This is accomplished by
* the following code:
*
* for (s = bands - 1; s >= 0; --s) {
* OI_INT bits = bitadjust + bitneeds[s];
* bits = bits < 2 ? 0 : bits;
* bits = bits > 16 ? 16 : bits;
* count += bits;
* }
*
* This loop can be optimized to perform 4 operations at a time as follows:
*
* Adjustment is computed as a 7 bit signed value and added to the bitneed.
*
* Negative allocations are zeroed by masking. (n & 0x40) >> 6 puts the
* sign bit into bit 0, adding this to 0x7F give us a mask of 0x80
* for -ve values and 0x7F for +ve values.
*
* n &= 0x7F + (n & 0x40) >> 6)
*
* Allocations greater than 16 are truncated to 16. Adjusted allocations are in
* the range 0..31 so we know that bit 4 indicates values >= 16. We use this bit
* to create a mask that zeroes bits 0 .. 3 if bit 4 is set.
*
* n &= (15 + (n >> 4))
*
* Allocations of 1 are disallowed. Add and shift creates a mask that
* eliminates the illegal value
*
* n &= ((n + 14) >> 4) | 0x1E
*
* These operations can be performed in 8 bits without overflowing so we can
* operate on 4 values at once.
*/
/*
* Encoder/Decoder
*
* Computes adjustment +/- of bitneeds to fill bitpool and returns overall
* adjustment and excess bits.
*
* @param bitpool The bitpool we have to work within
*
* @param bitneeds An array of bit needs (more acturately allocation prioritities) for each
* subband across all blocks in the SBC frame
*
* @param subbands The number of subbands over which the adkustment is calculated. For mono and
* dual mode this is 4 or 8, for stereo or joint stereo this is 8 or 16.
*
* @param bitcount A starting point for the adjustment
*
* @param excess Returns the excess bits after the adjustment
*
* @return The adjustment.
*/
OI_INT adjustToFitBitpool(const OI_UINT bitpool,
OI_UINT32 *bitneeds,
const OI_UINT subbands,
OI_UINT bitcount,
OI_UINT *excess)
{
OI_INT maxBitadjust = 0;
OI_INT bitadjust = (bitcount > bitpool) ? -8 : 8;
OI_INT chop = 8;
/*
* This is essentially a binary search for the optimal adjustment value.
*/
while ((bitcount != bitpool) && chop) {
OI_UINT32 total = 0;
OI_UINT count;
OI_UINT32 adjust4;
OI_INT i;
adjust4 = bitadjust & 0x7F;
adjust4 |= (adjust4 << 8);
adjust4 |= (adjust4 << 16);
for (i = ((subbands / 4) - 1); i >= 0; --i) {
OI_UINT32 mask;
OI_UINT32 n = bitneeds[i] + adjust4;
mask = 0x7F7F7F7F + ((n & 0x40404040) >> 6);
n &= mask;
mask = 0x0F0F0F0F + ((n & 0x10101010) >> 4);
n &= mask;
mask = (((n + 0x0E0E0E0E) >> 4) | 0x1E1E1E1E);
n &= mask;
total += n;
}
count = (total & 0xFFFF) + (total >> 16);
count = (count & 0xFF) + (count >> 8);
chop >>= 1;
if (count > bitpool) {
bitadjust -= chop;
} else {
maxBitadjust = bitadjust;
bitcount = count;
bitadjust += chop;
}
}
*excess = bitpool - bitcount;
return maxBitadjust;
}
/*
* The bit allocator trys to avoid single bit allocations except as a last resort. So in the case
* where a bitneed of 1 was passed over during the adsjustment phase 2 bits are now allocated.
*/
INLINE OI_INT allocAdjustedBits(OI_UINT8 *dest,
OI_INT bits,
OI_INT excess)
{
if (bits < 16) {
if (bits > 1) {
if (excess) {
++bits;
--excess;
}
} else if ((bits == 1) && (excess > 1)) {
bits = 2;
excess -= 2;
} else {
bits = 0;
}
} else {
bits = 16;
}
*dest = (OI_UINT8)bits;
return excess;
}
/*
* Excess bits not allocated by allocaAdjustedBits are allocated round-robin.
*/
INLINE OI_INT allocExcessBits(OI_UINT8 *dest,
OI_INT excess)
{
if (*dest < 16) {
*dest += 1;
return excess - 1;
} else {
return excess;
}
}
void oneChannelBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common,
BITNEED_UNION1 *bitneeds,
OI_UINT ch,
OI_UINT bitcount)
{
const OI_UINT8 nrof_subbands = common->frameInfo.nrof_subbands;
OI_UINT excess;
OI_UINT sb;
OI_INT bitadjust;
OI_UINT8 RESTRICT *allocBits;
{
OI_UINT ex;
bitadjust = adjustToFitBitpool(common->frameInfo.bitpool, bitneeds->uint32, nrof_subbands, bitcount, &ex);
/* We want the compiler to put excess into a register */
excess = ex;
}
/*
* Allocate adjusted bits
*/
allocBits = &common->bits.uint8[ch ? nrof_subbands : 0];
sb = 0;
while (sb < nrof_subbands) {
excess = allocAdjustedBits(&allocBits[sb], bitneeds->uint8[sb] + bitadjust, excess);
++sb;
}
sb = 0;
while (excess) {
excess = allocExcessBits(&allocBits[sb], excess);
++sb;
}
}
void monoBitAllocation(OI_CODEC_SBC_COMMON_CONTEXT *common)
{
BITNEED_UNION1 bitneeds;
OI_UINT bitcount;
OI_UINT bitpoolPreference = 0;
bitcount = computeBitneed(common, bitneeds.uint8, 0, &bitpoolPreference);
oneChannelBitAllocation(common, &bitneeds, 0, bitcount);
}
/**
@}
*/
+92 -92
View File
@@ -1,92 +1,92 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Functions for manipulating input bitstreams.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_stddefs.h"
#include "oi_bitstream.h"
#include "oi_assert.h"
PRIVATE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs,
const OI_BYTE *buffer)
{
bs->value = ((OI_INT32)buffer[0] << 16) | ((OI_INT32)buffer[1] << 8) | (buffer[2]);
bs->ptr.r = buffer + 3;
bs->bitPtr = 8;
}
PRIVATE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits)
{
OI_UINT32 result;
OI_BITSTREAM_READUINT(result, bits, bs->ptr.r, bs->value, bs->bitPtr);
return result;
}
PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs)
{
OI_UINT32 result;
OI_ASSERT(bs->bitPtr < 16);
OI_ASSERT(bs->bitPtr % 4 == 0);
if (bs->bitPtr == 8) {
result = bs->value << 8;
bs->bitPtr = 12;
} else {
result = bs->value << 12;
bs->value = (bs->value << 8) | *bs->ptr.r++;
bs->bitPtr = 8;
}
result >>= 28;
OI_ASSERT(result < (1u << 4));
return (OI_UINT8)result;
}
PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs)
{
OI_UINT32 result;
OI_ASSERT(bs->bitPtr == 8);
result = bs->value >> 16;
bs->value = (bs->value << 8) | *bs->ptr.r++;
return (OI_UINT8)result;
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Functions for manipulating input bitstreams.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_stddefs.h"
#include "oi_bitstream.h"
#include "oi_assert.h"
PRIVATE void OI_BITSTREAM_ReadInit(OI_BITSTREAM *bs,
const OI_BYTE *buffer)
{
bs->value = ((OI_INT32)buffer[0] << 16) | ((OI_INT32)buffer[1] << 8) | (buffer[2]);
bs->ptr.r = buffer + 3;
bs->bitPtr = 8;
}
PRIVATE OI_UINT32 OI_BITSTREAM_ReadUINT(OI_BITSTREAM *bs, OI_UINT bits)
{
OI_UINT32 result;
OI_BITSTREAM_READUINT(result, bits, bs->ptr.r, bs->value, bs->bitPtr);
return result;
}
PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT4Aligned(OI_BITSTREAM *bs)
{
OI_UINT32 result;
OI_ASSERT(bs->bitPtr < 16);
OI_ASSERT(bs->bitPtr % 4 == 0);
if (bs->bitPtr == 8) {
result = bs->value << 8;
bs->bitPtr = 12;
} else {
result = bs->value << 12;
bs->value = (bs->value << 8) | *bs->ptr.r++;
bs->bitPtr = 8;
}
result >>= 28;
OI_ASSERT(result < (1u << 4));
return (OI_UINT8)result;
}
PRIVATE OI_UINT8 OI_BITSTREAM_ReadUINT8Aligned(OI_BITSTREAM *bs)
{
OI_UINT32 result;
OI_ASSERT(bs->bitPtr == 8);
result = bs->value >> 16;
bs->value = (bs->value << 8) | *bs->ptr.r++;
return (OI_UINT8)result;
}
/**
@}
*/
+140 -140
View File
@@ -1,140 +1,140 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
This file exposes OINA-specific interfaces to decoder functions.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include <oi_codec_sbc_private.h>
OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 frequency,
OI_UINT8 mode,
OI_UINT8 subbands,
OI_UINT8 blocks,
OI_UINT8 alloc,
OI_UINT8 maxBitpool)
{
if (frequency > SBC_FREQ_48000) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (enhanced) {
#ifdef SBC_ENHANCED
if (subbands != SBC_SUBBANDS_8) {
return OI_STATUS_INVALID_PARAMETERS;
}
#else
return OI_STATUS_INVALID_PARAMETERS;
#endif
}
if (mode > SBC_JOINT_STEREO) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (subbands > SBC_SUBBANDS_8) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (blocks > SBC_BLOCKS_16) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (alloc > SBC_SNR) {
return OI_STATUS_INVALID_PARAMETERS;
}
#ifdef SBC_ENHANCED
context->common.frameInfo.enhanced = enhanced;
#else
context->common.frameInfo.enhanced = FALSE;
#endif
context->common.frameInfo.freqIndex = frequency;
context->common.frameInfo.mode = mode;
context->common.frameInfo.subbands = subbands;
context->common.frameInfo.blocks = blocks;
context->common.frameInfo.alloc = alloc;
context->common.frameInfo.bitpool = maxBitpool;
OI_SBC_ExpandFrameFields(&context->common.frameInfo);
if (context->common.frameInfo.nrof_channels >= context->common.pcmStride) {
return OI_STATUS_INVALID_PARAMETERS;
}
return OI_OK;
}
OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
return internal_DecodeRaw(context,
bitpool,
frameData,
frameBytes,
pcmData,
pcmBytes);
}
OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 subbands)
{
if (enhanced)
{
#ifdef SBC_ENHANCED
context->enhancedEnabled = TRUE;
#else
context->enhancedEnabled = FALSE;
#endif
}
else
{
context->enhancedEnabled = FALSE;
}
context->restrictSubbands = subbands;
context->limitFrameFormat = TRUE;
return OI_OK;
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
This file exposes OINA-specific interfaces to decoder functions.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include <oi_codec_sbc_private.h>
OI_STATUS OI_CODEC_SBC_DecoderConfigureRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 frequency,
OI_UINT8 mode,
OI_UINT8 subbands,
OI_UINT8 blocks,
OI_UINT8 alloc,
OI_UINT8 maxBitpool)
{
if (frequency > SBC_FREQ_48000) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (enhanced) {
#ifdef SBC_ENHANCED
if (subbands != SBC_SUBBANDS_8) {
return OI_STATUS_INVALID_PARAMETERS;
}
#else
return OI_STATUS_INVALID_PARAMETERS;
#endif
}
if (mode > SBC_JOINT_STEREO) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (subbands > SBC_SUBBANDS_8) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (blocks > SBC_BLOCKS_16) {
return OI_STATUS_INVALID_PARAMETERS;
}
if (alloc > SBC_SNR) {
return OI_STATUS_INVALID_PARAMETERS;
}
#ifdef SBC_ENHANCED
context->common.frameInfo.enhanced = enhanced;
#else
context->common.frameInfo.enhanced = FALSE;
#endif
context->common.frameInfo.freqIndex = frequency;
context->common.frameInfo.mode = mode;
context->common.frameInfo.subbands = subbands;
context->common.frameInfo.blocks = blocks;
context->common.frameInfo.alloc = alloc;
context->common.frameInfo.bitpool = maxBitpool;
OI_SBC_ExpandFrameFields(&context->common.frameInfo);
if (context->common.frameInfo.nrof_channels >= context->common.pcmStride) {
return OI_STATUS_INVALID_PARAMETERS;
}
return OI_OK;
}
OI_STATUS OI_CODEC_SBC_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
return internal_DecodeRaw(context,
bitpool,
frameData,
frameBytes,
pcmData,
pcmBytes);
}
OI_STATUS OI_CODEC_SBC_DecoderLimit(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_BOOL enhanced,
OI_UINT8 subbands)
{
if (enhanced)
{
#ifdef SBC_ENHANCED
context->enhancedEnabled = TRUE;
#else
context->enhancedEnabled = FALSE;
#endif
}
else
{
context->enhancedEnabled = FALSE;
}
context->restrictSubbands = subbands;
context->limitFrameFormat = TRUE;
return OI_OK;
}
/**
@}
*/
+272 -272
View File
@@ -1,272 +1,272 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
This file drives SBC decoding.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_bitstream.h"
#include <stdio.h>
const OI_CHAR * OI_Codec_Copyright = "Copyright 2002-2007 Open Interface North America, Inc. All rights reserved";
INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_BYTE maxChannels,
OI_BYTE pcmStride,
OI_BOOL enhanced)
{
OI_UINT i;
OI_STATUS status;
for (i = 0; i < sizeof(*context); i++) {
((char *)context)[i] = 0;
}
#ifdef SBC_ENHANCED
context->enhancedEnabled = enhanced ? TRUE : FALSE;
#else
context->enhancedEnabled = FALSE;
if (enhanced){
return OI_STATUS_INVALID_PARAMETERS;
}
#endif
status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride);
if (!OI_SUCCESS(status)) {
return status;
}
context->common.codecInfo = OI_Codec_Copyright;
context->common.maxBitneed = 0;
context->limitFrameFormat = FALSE;
OI_SBC_ExpandFrameFields(&context->common.frameInfo);
/*PLATFORM_DECODER_RESET(context);*/
return OI_OK;
}
/**
* Read the SBC header up to but not including the joint stereo mask. The syncword has already been
* examined, and the enhanced mode flag set, by FindSyncword.
*/
/* BK4BTSTACK_CHANGE START */
INLINE void OI_SBC_ReadHeader_mSBC(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data){
OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
OI_ASSERT(data[0] == OI_mSBC_SYNCWORD);
/* Avoid filling out all these strucutures if we already remember the values
* from last time. Just in case we get a stream corresponding to data[1] ==
* 0, DecoderReset is responsible for ensuring the lookup table entries have
* already been populated
*/
frame->reserved_for_future_use[0] = data[1];
frame->reserved_for_future_use[1] = data[2];
frame->freqIndex = 0;
frame->frequency = 16000;
frame->blocks = 4; // ?
frame->nrof_blocks = 15;
frame->mode = 0;
frame->nrof_channels = 1;
frame->alloc = SBC_LOUDNESS;
frame->subbands = 1;
frame->nrof_subbands = 8;
frame->bitpool = 26;
frame->crc = data[3];
frame->cachedInfo = 0;
}
/* BK4BTSTACK_CHANGE END */
INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data)
{
OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
OI_UINT8 d1;
OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD);
/* Avoid filling out all these strucutures if we already remember the values
* from last time. Just in case we get a stream corresponding to data[1] ==
* 0, DecoderReset is responsible for ensuring the lookup table entries have
* already been populated
*/
d1 = data[1];
if (d1 != frame->cachedInfo) {
frame->freqIndex = (d1 & (BIT7 | BIT6)) >> 6;
frame->frequency = freq_values[frame->freqIndex];
frame->blocks = (d1 & (BIT5 | BIT4)) >> 4;
frame->nrof_blocks = block_values[frame->blocks];
frame->mode = (d1 & (BIT3 | BIT2)) >> 2;
frame->nrof_channels = channel_values[frame->mode];
frame->alloc = (d1 & BIT1) >> 1;
frame->subbands = (d1 & BIT0);
frame->nrof_subbands = band_values[frame->subbands];
frame->cachedInfo = d1;
}
/*
* For decode, the bit allocator needs to know the bitpool value
*/
frame->bitpool = data[2];
frame->crc = data[3];
}
#define LOW(x) ((x)& 0xf)
#define HIGH(x) ((x) >> 4)
/*
* Read scalefactor values and prepare the bitstream for OI_SBC_ReadSamples
*/
PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common,
const OI_BYTE *b,
OI_BITSTREAM *bs)
{
OI_UINT i = common->frameInfo.nrof_subbands * common->frameInfo.nrof_channels;
OI_INT8 *scale_factor = common->scale_factor;
OI_UINT f;
if ((common->frameInfo.nrof_subbands == 8) || (common->frameInfo.mode != SBC_JOINT_STEREO)) {
if (common->frameInfo.mode == SBC_JOINT_STEREO) {
common->frameInfo.join = *b++;
} else {
common->frameInfo.join = 0;
}
i /= 2;
do {
*scale_factor++ = HIGH(f = *b++);
*scale_factor++ = LOW(f);
} while (--i);
/*
* In this case we know that the scale factors end on a byte boundary so all we need to do
* is initialize the bitstream.
*/
OI_BITSTREAM_ReadInit(bs, b);
} else {
OI_ASSERT(common->frameInfo.nrof_subbands == 4 && common->frameInfo.mode == SBC_JOINT_STEREO);
common->frameInfo.join = HIGH(f = *b++);
i = (i - 1) / 2;
do {
*scale_factor++ = LOW(f);
*scale_factor++ = HIGH(f = *b++);
} while (--i);
*scale_factor++ = LOW(f);
/*
* In 4-subband joint stereo mode, the joint stereo information ends on a half-byte
* boundary, so it's necessary to use the bitstream abstraction to read it, since
* OI_SBC_ReadSamples will need to pick up in mid-byte.
*/
OI_BITSTREAM_ReadInit(bs, b);
*scale_factor++ = OI_BITSTREAM_ReadUINT4Aligned(bs);
}
}
/** Read quantized subband samples from the input bitstream and expand them. */
PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT nrof_blocks = common->frameInfo.nrof_blocks;
OI_INT32 * RESTRICT s = common->subdata;
OI_UINT8 *ptr = global_bs->ptr.w;
OI_UINT32 value = global_bs->value;
OI_UINT bitPtr = global_bs->bitPtr;
const OI_UINT iter_count = common->frameInfo.nrof_channels * common->frameInfo.nrof_subbands / 4;
do {
OI_UINT i;
for (i = 0; i < iter_count; ++i) {
OI_UINT32 sf_by4 = ((OI_UINT32*)common->scale_factor)[i];
OI_UINT32 bits_by4 = common->bits.uint32[i];
OI_UINT n;
for (n = 0; n < 4; ++n) {
OI_INT32 dequant;
OI_UINT bits;
OI_INT sf;
if (OI_CPU_BYTE_ORDER == OI_LITTLE_ENDIAN_BYTE_ORDER) {
bits = bits_by4 & 0xFF;
bits_by4 >>= 8;
sf = sf_by4 & 0xFF;
sf_by4 >>= 8;
} else {
bits = (bits_by4 >> 24) & 0xFF;
bits_by4 <<= 8;
sf = (sf_by4 >> 24) & 0xFF;
sf_by4 <<= 8;
}
if (bits) {
OI_UINT32 raw;
// return raw == audio sample (uint16)
// bits == number of bits to read from stream
// ptr == position in stream
// value == 32bit value
// bitPtr offset in 32bit value
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
// dequant == sb_sample (int32)
dequant = OI_SBC_Dequant(raw, sf, bits);
} else {
dequant = 0;
}
*s++ = dequant;
}
}
} while (--nrof_blocks);
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
This file drives SBC decoding.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_bitstream.h"
#include <stdio.h>
const OI_CHAR * OI_Codec_Copyright = "Copyright 2002-2007 Open Interface North America, Inc. All rights reserved";
INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_BYTE maxChannels,
OI_BYTE pcmStride,
OI_BOOL enhanced)
{
OI_UINT i;
OI_STATUS status;
for (i = 0; i < sizeof(*context); i++) {
((char *)context)[i] = 0;
}
#ifdef SBC_ENHANCED
context->enhancedEnabled = enhanced ? TRUE : FALSE;
#else
context->enhancedEnabled = FALSE;
if (enhanced){
return OI_STATUS_INVALID_PARAMETERS;
}
#endif
status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride);
if (!OI_SUCCESS(status)) {
return status;
}
context->common.codecInfo = OI_Codec_Copyright;
context->common.maxBitneed = 0;
context->limitFrameFormat = FALSE;
OI_SBC_ExpandFrameFields(&context->common.frameInfo);
/*PLATFORM_DECODER_RESET(context);*/
return OI_OK;
}
/**
* Read the SBC header up to but not including the joint stereo mask. The syncword has already been
* examined, and the enhanced mode flag set, by FindSyncword.
*/
/* BK4BTSTACK_CHANGE START */
INLINE void OI_SBC_ReadHeader_mSBC(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data){
OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
OI_ASSERT(data[0] == OI_mSBC_SYNCWORD);
/* Avoid filling out all these strucutures if we already remember the values
* from last time. Just in case we get a stream corresponding to data[1] ==
* 0, DecoderReset is responsible for ensuring the lookup table entries have
* already been populated
*/
frame->reserved_for_future_use[0] = data[1];
frame->reserved_for_future_use[1] = data[2];
frame->freqIndex = 0;
frame->frequency = 16000;
frame->blocks = 4; // ?
frame->nrof_blocks = 15;
frame->mode = 0;
frame->nrof_channels = 1;
frame->alloc = SBC_LOUDNESS;
frame->subbands = 1;
frame->nrof_subbands = 8;
frame->bitpool = 26;
frame->crc = data[3];
frame->cachedInfo = 0;
}
/* BK4BTSTACK_CHANGE END */
INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE *data)
{
OI_CODEC_SBC_FRAME_INFO *frame = &common->frameInfo;
OI_UINT8 d1;
OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD);
/* Avoid filling out all these strucutures if we already remember the values
* from last time. Just in case we get a stream corresponding to data[1] ==
* 0, DecoderReset is responsible for ensuring the lookup table entries have
* already been populated
*/
d1 = data[1];
if (d1 != frame->cachedInfo) {
frame->freqIndex = (d1 & (BIT7 | BIT6)) >> 6;
frame->frequency = freq_values[frame->freqIndex];
frame->blocks = (d1 & (BIT5 | BIT4)) >> 4;
frame->nrof_blocks = block_values[frame->blocks];
frame->mode = (d1 & (BIT3 | BIT2)) >> 2;
frame->nrof_channels = channel_values[frame->mode];
frame->alloc = (d1 & BIT1) >> 1;
frame->subbands = (d1 & BIT0);
frame->nrof_subbands = band_values[frame->subbands];
frame->cachedInfo = d1;
}
/*
* For decode, the bit allocator needs to know the bitpool value
*/
frame->bitpool = data[2];
frame->crc = data[3];
}
#define LOW(x) ((x)& 0xf)
#define HIGH(x) ((x) >> 4)
/*
* Read scalefactor values and prepare the bitstream for OI_SBC_ReadSamples
*/
PRIVATE void OI_SBC_ReadScalefactors(OI_CODEC_SBC_COMMON_CONTEXT *common,
const OI_BYTE *b,
OI_BITSTREAM *bs)
{
OI_UINT i = common->frameInfo.nrof_subbands * common->frameInfo.nrof_channels;
OI_INT8 *scale_factor = common->scale_factor;
OI_UINT f;
if ((common->frameInfo.nrof_subbands == 8) || (common->frameInfo.mode != SBC_JOINT_STEREO)) {
if (common->frameInfo.mode == SBC_JOINT_STEREO) {
common->frameInfo.join = *b++;
} else {
common->frameInfo.join = 0;
}
i /= 2;
do {
*scale_factor++ = HIGH(f = *b++);
*scale_factor++ = LOW(f);
} while (--i);
/*
* In this case we know that the scale factors end on a byte boundary so all we need to do
* is initialize the bitstream.
*/
OI_BITSTREAM_ReadInit(bs, b);
} else {
OI_ASSERT(common->frameInfo.nrof_subbands == 4 && common->frameInfo.mode == SBC_JOINT_STEREO);
common->frameInfo.join = HIGH(f = *b++);
i = (i - 1) / 2;
do {
*scale_factor++ = LOW(f);
*scale_factor++ = HIGH(f = *b++);
} while (--i);
*scale_factor++ = LOW(f);
/*
* In 4-subband joint stereo mode, the joint stereo information ends on a half-byte
* boundary, so it's necessary to use the bitstream abstraction to read it, since
* OI_SBC_ReadSamples will need to pick up in mid-byte.
*/
OI_BITSTREAM_ReadInit(bs, b);
*scale_factor++ = OI_BITSTREAM_ReadUINT4Aligned(bs);
}
}
/** Read quantized subband samples from the input bitstream and expand them. */
PRIVATE void OI_SBC_ReadSamples(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT nrof_blocks = common->frameInfo.nrof_blocks;
OI_INT32 * RESTRICT s = common->subdata;
OI_UINT8 *ptr = global_bs->ptr.w;
OI_UINT32 value = global_bs->value;
OI_UINT bitPtr = global_bs->bitPtr;
const OI_UINT iter_count = common->frameInfo.nrof_channels * common->frameInfo.nrof_subbands / 4;
do {
OI_UINT i;
for (i = 0; i < iter_count; ++i) {
OI_UINT32 sf_by4 = ((OI_UINT32*)common->scale_factor)[i];
OI_UINT32 bits_by4 = common->bits.uint32[i];
OI_UINT n;
for (n = 0; n < 4; ++n) {
OI_INT32 dequant;
OI_UINT bits;
OI_INT sf;
if (OI_CPU_BYTE_ORDER == OI_LITTLE_ENDIAN_BYTE_ORDER) {
bits = bits_by4 & 0xFF;
bits_by4 >>= 8;
sf = sf_by4 & 0xFF;
sf_by4 >>= 8;
} else {
bits = (bits_by4 >> 24) & 0xFF;
bits_by4 <<= 8;
sf = (sf_by4 >> 24) & 0xFF;
sf_by4 <<= 8;
}
if (bits) {
OI_UINT32 raw;
// return raw == audio sample (uint16)
// bits == number of bits to read from stream
// ptr == position in stream
// value == 32bit value
// bitPtr offset in 32bit value
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
// dequant == sb_sample (int32)
dequant = OI_SBC_Dequant(raw, sf, bits);
} else {
dequant = 0;
}
*s++ = dequant;
}
}
} while (--nrof_blocks);
}
/**
@}
*/
+498 -498
View File
@@ -1,498 +1,498 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addtogroup codec_internal */
/**@{*/
#include "oi_codec_sbc_private.h"
#include "oi_bitstream.h"
#define SPECIALIZE_READ_SAMPLES_JOINT
/**
* Scans through a buffer looking for a codec syncword. If the decoder has been
* set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search
* for both a standard and an enhanced syncword.
*/
PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes);
PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes)
{
#ifdef SBC_ENHANCED
OI_BYTE search1 = OI_SBC_SYNCWORD;
OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD;
#endif // SBC_ENHANCED
if (*frameBytes == 0) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
#ifdef SBC_ENHANCED
if (context->limitFrameFormat && context->enhancedEnabled){
/* If the context is restricted, only search for specified SYNCWORD */
search1 = search2;
} else if (context->enhancedEnabled == FALSE) {
/* If enhanced is not enabled, only search for classic SBC SYNCWORD*/
search2 = search1;
}
while (*frameBytes && (**frameData != search1) && (**frameData != search2)) {
(*frameBytes)--;
(*frameData)++;
}
if (*frameBytes) {
/* Syncword found, *frameData points to it, and *frameBytes correctly
* reflects the number of bytes available to read, including the
* syncword. */
context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD);
return OI_OK;
} else {
/* No syncword was found anywhere in the provided input data.
* *frameData points past the end of the original input, and
* *frameBytes is 0. */
return OI_CODEC_SBC_NO_SYNCWORD;
}
#else // SBC_ENHANCED
/* BK4BTSTACK_CHANGE START */
OI_UINT8 syncword = OI_SBC_SYNCWORD;
if (context->common.frameInfo.mSBCEnabled){
syncword = OI_mSBC_SYNCWORD;
}
/* BK4BTSTACK_CHANGE END */
while (*frameBytes && (**frameData != syncword)) {
(*frameBytes)--;
(*frameData)++;
}
if (*frameBytes) {
/* Syncword found, *frameData points to it, and *frameBytes correctly
* reflects the number of bytes available to read, including the
* syncword. */
context->common.frameInfo.enhanced = FALSE;
return OI_OK;
} else {
/* No syncword was found anywhere in the provided input data.
* *frameData points past the end of the original input, and
* *frameBytes is 0. */
return OI_CODEC_SBC_NO_SYNCWORD;
}
#endif // SBC_ENHANCED
}
static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE *bodyData,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes,
OI_BOOL allowPartial)
{
OI_BITSTREAM bs;
OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands;
OI_UINT decode_block_count;
/*
* Based on the header data, make sure that there is enough room to write the output samples.
*/
if ((*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride)) && !allowPartial) {
/* If we're not allowing partial decodes, we need room for the entire
* codec frame */
TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
} else if (*pcmBytes < (sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride)) {
/* Even if we're allowing partials, we can still only decode on a frame
* boundary */
return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
}
if (context->bufferedBlocks == 0) {
TRACE(("Reading scalefactors"));
OI_SBC_ReadScalefactors(&context->common, bodyData, &bs);
TRACE(("Computing bit allocation"));
OI_SBC_ComputeBitAllocation(&context->common);
TRACE(("Reading samples"));
if (context->common.frameInfo.mode == SBC_JOINT_STEREO) {
OI_SBC_ReadSamplesJoint(context, &bs);
} else {
OI_SBC_ReadSamples(context, &bs);
}
context->bufferedBlocks = context->common.frameInfo.nrof_blocks;
}
if (allowPartial) {
decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands;
if (decode_block_count > context->bufferedBlocks) {
decode_block_count = context->bufferedBlocks;
}
} else {
decode_block_count = context->common.frameInfo.nrof_blocks;
}
TRACE(("Synthesizing frame"));
{
OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks;
OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count);
}
OI_ASSERT(context->bufferedBlocks >= decode_block_count);
context->bufferedBlocks -= decode_block_count;
frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands;
/*
* When decoding mono into a stride-2 array, copy pcm data to second channel
*/
if ((context->common.frameInfo.nrof_channels == 1) && (context->common.pcmStride == 2)) {
OI_UINT i;
for (i = 0; i < frameSamples; ++i) {
pcmData[(2*i)+1] = pcmData[2*i];
}
}
/*
* Return number of pcm bytes generated by the decode operation.
*/
*pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride;
if (context->bufferedBlocks > 0) {
return OI_CODEC_SBC_PARTIAL_DECODE;
} else {
return OI_OK;
}
}
PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
OI_STATUS status;
OI_UINT bodyLen;
TRACE(("+OI_CODEC_SBC_DecodeRaw"));
if (context->bufferedBlocks == 0) {
/*
* The bitallocator needs to know the bitpool value.
*/
context->common.frameInfo.bitpool = bitpool;
/*
* Compute the frame length and check we have enough frame data to proceed
*/
bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN;
if (*frameBytes < bodyLen) {
TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
} else {
bodyLen = 0;
}
/*
* Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of
* tones.
*/
status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE);
if (OI_SUCCESS(status) || (status == OI_CODEC_SBC_PARTIAL_DECODE)) {
*frameData += bodyLen;
*frameBytes -= bodyLen;
}
TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status));
return status;
}
OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride,
OI_BOOL enhanced)
{
return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced);
}
/* BK4BTSTACK_CHANGE START */
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes)
{
OI_STATUS status = OI_CODEC_SBC_DecoderReset(context, decoderData, decoderDataBytes, 1, 1, FALSE);
context->common.frameInfo.mSBCEnabled = TRUE;
return status;
}
/* BK4BTSTACK_CHANGE END */
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
OI_STATUS status;
OI_UINT framelen;
OI_UINT8 crc;
TRACE(("+OI_CODEC_SBC_DecodeFrame"));
TRACE(("Finding syncword"));
status = FindSyncword(context, frameData, frameBytes);
if (!OI_SUCCESS(status)) {
return status;
}
/* Make sure enough data remains to read the header. */
if (*frameBytes < SBC_HEADER_LEN) {
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
TRACE(("Reading Header"));
if (context->common.frameInfo.mSBCEnabled){
OI_SBC_ReadHeader_mSBC(&context->common, *frameData);
} else {
OI_SBC_ReadHeader(&context->common, *frameData);
}
/*
* Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need
* to ensure that the SBC parameters for this frame are compatible with the restrictions imposed
* by the loaded overlays.
*/
if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) {
ERROR(("SBC parameters incompatible with loaded overlay"));
return OI_STATUS_INVALID_PARAMETERS;
}
TRACE(("Frame: "));
if (context->common.frameInfo.nrof_channels > context->common.maxChannels) {
ERROR(("SBC parameters incompatible with number of channels specified during reset"));
return OI_STATUS_INVALID_PARAMETERS;
}
if ((context->common.pcmStride < 1) || (context->common.pcmStride > 2)) {
ERROR(("PCM stride not set correctly during reset"));
return OI_STATUS_INVALID_PARAMETERS;
}
/*
* At this point a header has been read. However, it's possible that we found a false syncword,
* so the header data might be invalid. Make sure we have enough bytes to read in the
* CRC-protected header, but don't require we have the whole frame. That way, if it turns out
* that we're acting on bogus header data, we don't stall the decoding process by waiting for
* data that we don't actually need.
*/
framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo);
if (*frameBytes < framelen) {
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
TRACE(("Calculating checksum"));
if (context->common.frameInfo.mSBCEnabled){
crc = OI_SBC_CalculateChecksum_mSBC(&context->common.frameInfo, *frameData);
} else {
crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
}
if (crc != context->common.frameInfo.crc) {
TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc));
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH"));
return OI_CODEC_SBC_CHECKSUM_MISMATCH;
}
#ifdef OI_DEBUG
/*
* Make sure the bitpool values are sane.
*/
if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) {
ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool));
return OI_STATUS_INVALID_PARAMETERS;
}
if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) {
ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo)));
return OI_STATUS_INVALID_PARAMETERS;
}
#endif
/*
* Now decode the SBC data. Partial decode is not yet implemented for an SBC
* stream, so pass FALSE to decode body to have it enforce the old rule that
* you have to decode a whole packet at a time.
*/
status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE);
if (OI_SUCCESS(status)) {
*frameData += framelen;
*frameBytes -= framelen;
}
TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status));
return status;
}
OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes)
{
OI_STATUS status;
OI_UINT framelen;
OI_UINT headerlen;
OI_UINT8 crc;
status = FindSyncword(context, frameData, frameBytes);
if (!OI_SUCCESS(status)) {
return status;
}
if (*frameBytes < SBC_HEADER_LEN) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
OI_SBC_ReadHeader(&context->common, *frameData);
framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen);
if (*frameBytes < headerlen) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
if (crc != context->common.frameInfo.crc) {
return OI_CODEC_SBC_CHECKSUM_MISMATCH;
}
if (*frameBytes < framelen) {
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
context->bufferedBlocks = 0;
*frameData += framelen;
*frameBytes -= framelen;
return OI_OK;
}
OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData,
OI_UINT32 frameBytes)
{
OI_UINT8 mode;
OI_UINT8 blocks;
OI_UINT8 subbands;
OI_UINT8 frameCount = 0;
OI_UINT frameLen;
while (frameBytes){
while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){
frameData++;
frameBytes--;
}
if (frameBytes < SBC_HEADER_LEN) {
return frameCount;
}
/* Extract and translate required fields from Header */
subbands = mode = blocks = frameData[1];;
mode = (mode & (BIT3 | BIT2)) >> 2;
blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4];
subbands = band_values[(subbands & BIT0)];
/* Inline logic to avoid corrupting context */
frameLen = blocks * frameData[2];
switch (mode){
case SBC_JOINT_STEREO:
frameLen += subbands + (8 * subbands);
break;
case SBC_DUAL_CHANNEL:
frameLen *= 2;
/* fall through */
default:
if (mode == SBC_MONO){
frameLen += 4*subbands;
} else {
frameLen += 8*subbands;
}
}
frameCount++;
frameLen = SBC_HEADER_LEN + ((frameLen + 7) / 8);
if (frameBytes > frameLen){
frameBytes -= frameLen;
frameData += frameLen;
} else {
frameBytes = 0;
}
}
return frameCount;
}
/** Read quantized subband samples from the input bitstream and expand them. */
#ifdef SPECIALIZE_READ_SAMPLES_JOINT
PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 4
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 8
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
static const READ_SAMPLES SpecializedReadSamples[] = {
OI_SBC_ReadSamplesJoint4,
OI_SBC_ReadSamplesJoint8
};
#endif /* SPECIALIZE_READ_SAMPLES_JOINT */
PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
#ifdef SPECIALIZE_READ_SAMPLES_JOINT
OI_ASSERT((nrof_subbands >> 3u) <= 1u);
SpecializedReadSamples[nrof_subbands >> 3](context, global_bs);
#else
#define NROF_SUBBANDS nrof_subbands
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
#endif /* SPECIALIZE_READ_SAMPLES_JOINT */
}
/**@}*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2006 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addtogroup codec_internal */
/**@{*/
#include "oi_codec_sbc_private.h"
#include "oi_bitstream.h"
#define SPECIALIZE_READ_SAMPLES_JOINT
/**
* Scans through a buffer looking for a codec syncword. If the decoder has been
* set for enhanced operation using OI_CODEC_SBC_DecoderReset(), it will search
* for both a standard and an enhanced syncword.
*/
PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes);
PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes)
{
#ifdef SBC_ENHANCED
OI_BYTE search1 = OI_SBC_SYNCWORD;
OI_BYTE search2 = OI_SBC_ENHANCED_SYNCWORD;
#endif // SBC_ENHANCED
if (*frameBytes == 0) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
#ifdef SBC_ENHANCED
if (context->limitFrameFormat && context->enhancedEnabled){
/* If the context is restricted, only search for specified SYNCWORD */
search1 = search2;
} else if (context->enhancedEnabled == FALSE) {
/* If enhanced is not enabled, only search for classic SBC SYNCWORD*/
search2 = search1;
}
while (*frameBytes && (**frameData != search1) && (**frameData != search2)) {
(*frameBytes)--;
(*frameData)++;
}
if (*frameBytes) {
/* Syncword found, *frameData points to it, and *frameBytes correctly
* reflects the number of bytes available to read, including the
* syncword. */
context->common.frameInfo.enhanced = (**frameData == OI_SBC_ENHANCED_SYNCWORD);
return OI_OK;
} else {
/* No syncword was found anywhere in the provided input data.
* *frameData points past the end of the original input, and
* *frameBytes is 0. */
return OI_CODEC_SBC_NO_SYNCWORD;
}
#else // SBC_ENHANCED
/* BK4BTSTACK_CHANGE START */
OI_UINT8 syncword = OI_SBC_SYNCWORD;
if (context->common.frameInfo.mSBCEnabled){
syncword = OI_mSBC_SYNCWORD;
}
/* BK4BTSTACK_CHANGE END */
while (*frameBytes && (**frameData != syncword)) {
(*frameBytes)--;
(*frameData)++;
}
if (*frameBytes) {
/* Syncword found, *frameData points to it, and *frameBytes correctly
* reflects the number of bytes available to read, including the
* syncword. */
context->common.frameInfo.enhanced = FALSE;
return OI_OK;
} else {
/* No syncword was found anywhere in the provided input data.
* *frameData points past the end of the original input, and
* *frameBytes is 0. */
return OI_CODEC_SBC_NO_SYNCWORD;
}
#endif // SBC_ENHANCED
}
static OI_STATUS DecodeBody(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE *bodyData,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes,
OI_BOOL allowPartial)
{
OI_BITSTREAM bs;
OI_UINT frameSamples = context->common.frameInfo.nrof_blocks * context->common.frameInfo.nrof_subbands;
OI_UINT decode_block_count;
/*
* Based on the header data, make sure that there is enough room to write the output samples.
*/
if ((*pcmBytes < (sizeof(OI_INT16) * frameSamples * context->common.pcmStride)) && !allowPartial) {
/* If we're not allowing partial decodes, we need room for the entire
* codec frame */
TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
} else if (*pcmBytes < (sizeof (OI_INT16) * context->common.frameInfo.nrof_subbands * context->common.pcmStride)) {
/* Even if we're allowing partials, we can still only decode on a frame
* boundary */
return OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA;
}
if (context->bufferedBlocks == 0) {
TRACE(("Reading scalefactors"));
OI_SBC_ReadScalefactors(&context->common, bodyData, &bs);
TRACE(("Computing bit allocation"));
OI_SBC_ComputeBitAllocation(&context->common);
TRACE(("Reading samples"));
if (context->common.frameInfo.mode == SBC_JOINT_STEREO) {
OI_SBC_ReadSamplesJoint(context, &bs);
} else {
OI_SBC_ReadSamples(context, &bs);
}
context->bufferedBlocks = context->common.frameInfo.nrof_blocks;
}
if (allowPartial) {
decode_block_count = *pcmBytes / sizeof(OI_INT16) / context->common.pcmStride / context->common.frameInfo.nrof_subbands;
if (decode_block_count > context->bufferedBlocks) {
decode_block_count = context->bufferedBlocks;
}
} else {
decode_block_count = context->common.frameInfo.nrof_blocks;
}
TRACE(("Synthesizing frame"));
{
OI_UINT start_block = context->common.frameInfo.nrof_blocks - context->bufferedBlocks;
OI_SBC_SynthFrame(context, pcmData, start_block, decode_block_count);
}
OI_ASSERT(context->bufferedBlocks >= decode_block_count);
context->bufferedBlocks -= decode_block_count;
frameSamples = decode_block_count * context->common.frameInfo.nrof_subbands;
/*
* When decoding mono into a stride-2 array, copy pcm data to second channel
*/
if ((context->common.frameInfo.nrof_channels == 1) && (context->common.pcmStride == 2)) {
OI_UINT i;
for (i = 0; i < frameSamples; ++i) {
pcmData[(2*i)+1] = pcmData[2*i];
}
}
/*
* Return number of pcm bytes generated by the decode operation.
*/
*pcmBytes = frameSamples * sizeof(OI_INT16) * context->common.pcmStride;
if (context->bufferedBlocks > 0) {
return OI_CODEC_SBC_PARTIAL_DECODE;
} else {
return OI_OK;
}
}
PRIVATE OI_STATUS internal_DecodeRaw(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT8 bitpool,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
OI_STATUS status;
OI_UINT bodyLen;
TRACE(("+OI_CODEC_SBC_DecodeRaw"));
if (context->bufferedBlocks == 0) {
/*
* The bitallocator needs to know the bitpool value.
*/
context->common.frameInfo.bitpool = bitpool;
/*
* Compute the frame length and check we have enough frame data to proceed
*/
bodyLen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo) - SBC_HEADER_LEN;
if (*frameBytes < bodyLen) {
TRACE(("-OI_CODEC_SBC_Decode: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
} else {
bodyLen = 0;
}
/*
* Decode the SBC data. Pass TRUE to DecodeBody to allow partial decoding of
* tones.
*/
status = DecodeBody(context, *frameData, pcmData, pcmBytes, TRUE);
if (OI_SUCCESS(status) || (status == OI_CODEC_SBC_PARTIAL_DECODE)) {
*frameData += bodyLen;
*frameBytes -= bodyLen;
}
TRACE(("-OI_CODEC_SBC_DecodeRaw: %d", status));
return status;
}
OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes,
OI_UINT8 maxChannels,
OI_UINT8 pcmStride,
OI_BOOL enhanced)
{
return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced);
}
/* BK4BTSTACK_CHANGE START */
OI_STATUS OI_CODEC_mSBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
OI_UINT32 *decoderData,
OI_UINT32 decoderDataBytes)
{
OI_STATUS status = OI_CODEC_SBC_DecoderReset(context, decoderData, decoderDataBytes, 1, 1, FALSE);
context->common.frameInfo.mSBCEnabled = TRUE;
return status;
}
/* BK4BTSTACK_CHANGE END */
OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes,
OI_INT16 *pcmData,
OI_UINT32 *pcmBytes)
{
OI_STATUS status;
OI_UINT framelen;
OI_UINT8 crc;
TRACE(("+OI_CODEC_SBC_DecodeFrame"));
TRACE(("Finding syncword"));
status = FindSyncword(context, frameData, frameBytes);
if (!OI_SUCCESS(status)) {
return status;
}
/* Make sure enough data remains to read the header. */
if (*frameBytes < SBC_HEADER_LEN) {
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
TRACE(("Reading Header"));
if (context->common.frameInfo.mSBCEnabled){
OI_SBC_ReadHeader_mSBC(&context->common, *frameData);
} else {
OI_SBC_ReadHeader(&context->common, *frameData);
}
/*
* Some implementations load the decoder into RAM and use overlays for 4 vs 8 subbands. We need
* to ensure that the SBC parameters for this frame are compatible with the restrictions imposed
* by the loaded overlays.
*/
if (context->limitFrameFormat && (context->common.frameInfo.subbands != context->restrictSubbands)) {
ERROR(("SBC parameters incompatible with loaded overlay"));
return OI_STATUS_INVALID_PARAMETERS;
}
TRACE(("Frame: "));
if (context->common.frameInfo.nrof_channels > context->common.maxChannels) {
ERROR(("SBC parameters incompatible with number of channels specified during reset"));
return OI_STATUS_INVALID_PARAMETERS;
}
if ((context->common.pcmStride < 1) || (context->common.pcmStride > 2)) {
ERROR(("PCM stride not set correctly during reset"));
return OI_STATUS_INVALID_PARAMETERS;
}
/*
* At this point a header has been read. However, it's possible that we found a false syncword,
* so the header data might be invalid. Make sure we have enough bytes to read in the
* CRC-protected header, but don't require we have the whole frame. That way, if it turns out
* that we're acting on bogus header data, we don't stall the decoding process by waiting for
* data that we don't actually need.
*/
framelen = OI_CODEC_SBC_CalculateFramelen(&context->common.frameInfo);
if (*frameBytes < framelen) {
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA"));
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
TRACE(("Calculating checksum"));
if (context->common.frameInfo.mSBCEnabled){
crc = OI_SBC_CalculateChecksum_mSBC(&context->common.frameInfo, *frameData);
} else {
crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
}
if (crc != context->common.frameInfo.crc) {
TRACE(("CRC Mismatch: calc=%02x read=%02x\n", crc, context->common.frameInfo.crc));
TRACE(("-OI_CODEC_SBC_DecodeFrame: OI_CODEC_SBC_CHECKSUM_MISMATCH"));
return OI_CODEC_SBC_CHECKSUM_MISMATCH;
}
#ifdef OI_DEBUG
/*
* Make sure the bitpool values are sane.
*/
if ((context->common.frameInfo.bitpool < SBC_MIN_BITPOOL) && !context->common.frameInfo.enhanced) {
ERROR(("Bitpool too small: %d (must be >= 2)", context->common.frameInfo.bitpool));
return OI_STATUS_INVALID_PARAMETERS;
}
if (context->common.frameInfo.bitpool > OI_SBC_MaxBitpool(&context->common.frameInfo)) {
ERROR(("Bitpool too large: %d (must be <= %ld)", context->common.frameInfo.bitpool, OI_SBC_MaxBitpool(&context->common.frameInfo)));
return OI_STATUS_INVALID_PARAMETERS;
}
#endif
/*
* Now decode the SBC data. Partial decode is not yet implemented for an SBC
* stream, so pass FALSE to decode body to have it enforce the old rule that
* you have to decode a whole packet at a time.
*/
status = DecodeBody(context, *frameData + SBC_HEADER_LEN, pcmData, pcmBytes, FALSE);
if (OI_SUCCESS(status)) {
*frameData += framelen;
*frameBytes -= framelen;
}
TRACE(("-OI_CODEC_SBC_DecodeFrame: %d", status));
return status;
}
OI_STATUS OI_CODEC_SBC_SkipFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
const OI_BYTE **frameData,
OI_UINT32 *frameBytes)
{
OI_STATUS status;
OI_UINT framelen;
OI_UINT headerlen;
OI_UINT8 crc;
status = FindSyncword(context, frameData, frameBytes);
if (!OI_SUCCESS(status)) {
return status;
}
if (*frameBytes < SBC_HEADER_LEN) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
OI_SBC_ReadHeader(&context->common, *frameData);
framelen = OI_SBC_CalculateFrameAndHeaderlen(&context->common.frameInfo, &headerlen);
if (*frameBytes < headerlen) {
return OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA;
}
crc = OI_SBC_CalculateChecksum(&context->common.frameInfo, *frameData);
if (crc != context->common.frameInfo.crc) {
return OI_CODEC_SBC_CHECKSUM_MISMATCH;
}
if (*frameBytes < framelen) {
return OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA;
}
context->bufferedBlocks = 0;
*frameData += framelen;
*frameBytes -= framelen;
return OI_OK;
}
OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData,
OI_UINT32 frameBytes)
{
OI_UINT8 mode;
OI_UINT8 blocks;
OI_UINT8 subbands;
OI_UINT8 frameCount = 0;
OI_UINT frameLen;
while (frameBytes){
while (frameBytes && ((frameData[0] & 0xFE) != 0x9C)){
frameData++;
frameBytes--;
}
if (frameBytes < SBC_HEADER_LEN) {
return frameCount;
}
/* Extract and translate required fields from Header */
subbands = mode = blocks = frameData[1];;
mode = (mode & (BIT3 | BIT2)) >> 2;
blocks = block_values[(blocks & (BIT5 | BIT4)) >> 4];
subbands = band_values[(subbands & BIT0)];
/* Inline logic to avoid corrupting context */
frameLen = blocks * frameData[2];
switch (mode){
case SBC_JOINT_STEREO:
frameLen += subbands + (8 * subbands);
break;
case SBC_DUAL_CHANNEL:
frameLen *= 2;
/* fall through */
default:
if (mode == SBC_MONO){
frameLen += 4*subbands;
} else {
frameLen += 8*subbands;
}
}
frameCount++;
frameLen = SBC_HEADER_LEN + ((frameLen + 7) / 8);
if (frameBytes > frameLen){
frameBytes -= frameLen;
frameData += frameLen;
} else {
frameBytes = 0;
}
}
return frameCount;
}
/** Read quantized subband samples from the input bitstream and expand them. */
#ifdef SPECIALIZE_READ_SAMPLES_JOINT
PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 4
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
PRIVATE void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 8
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
typedef void (*READ_SAMPLES)(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs);
static const READ_SAMPLES SpecializedReadSamples[] = {
OI_SBC_ReadSamplesJoint4,
OI_SBC_ReadSamplesJoint8
};
#endif /* SPECIALIZE_READ_SAMPLES_JOINT */
PRIVATE void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_BITSTREAM *global_bs)
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
#ifdef SPECIALIZE_READ_SAMPLES_JOINT
OI_ASSERT((nrof_subbands >> 3u) <= 1u);
SpecializedReadSamples[nrof_subbands >> 3](context, global_bs);
#else
#define NROF_SUBBANDS nrof_subbands
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
#endif /* SPECIALIZE_READ_SAMPLES_JOINT */
}
/**@}*/
+211 -211
View File
@@ -1,211 +1,211 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Dequantizer for SBC decoder; reconstructs quantized representation of subband samples.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
/**
This function is a fixed-point approximation of a modification of the following
dequantization operation defined in the spec, as inferred from section 12.6.4:
@code
dequant = 2^(scale_factor+1) * ((raw * 2.0 + 1.0) / ((2^bits) - 1) - 1)
2 <= bits <= 16
0 <= raw < (2^bits)-1 (the -1 is because quantized values with all 1's are forbidden)
-65535 < dequant < 65535
@endcode
The code below computes the dequantized value divided by a scaling constant
equal to about 1.38. This constant is chosen to ensure that the entry in the
dequant_long_scaled table for 16 bits is as accurate as possible, since it has
the least relative precision available to it due to its small magnitude.
This routine outputs in Q16.15 format.
The helper array dequant_long is defined as follows:
@code
dequant_long_long[bits] = round(2^31 * 1/((2^bits - 1) / 1.38...) for 2 <= bits <= 16
@endcode
Additionally, the table entries have the following property:
@code
dequant_long_scaled[bits] <= 2^31 / ((2^bits - 1)) for 2 <= bits <= 16
@endcode
Therefore
@code
d = 2 * raw + 1 1 <= d <= 2^bits - 2
d' = d * dequant_long[bits]
d * dequant_long_scaled[bits] <= (2^bits - 2) * (2^31 / (2^bits - 1))
d * dequant_long_scaled[bits] <= 2^31 * (2^bits - 2)/(2^bits - 1) < 2^31
@endcode
Therefore, d' doesn't overflow a signed 32-bit value.
@code
d' =~ 2^31 * (raw * 2.0 + 1.0) / (2^bits - 1) / 1.38...
result = d' - 2^31/1.38... =~ 2^31 * ((raw * 2.0 + 1.0) / (2^bits - 1) - 1) / 1.38...
result is therefore a scaled approximation to dequant. It remains only to
turn 2^31 into 2^(scale_factor+1). Since we're aiming for Q16.15 format,
this is achieved by shifting right by (15-scale_factor):
(2^31 * x) >> (15-scale_factor) =~ 2^(31-15+scale_factor) * x = 2^15 * 2^(1+scale_factor) * x
@endcode
*/
#include <oi_codec_sbc_private.h>
#ifndef SBC_DEQUANT_LONG_SCALED_OFFSET
#define SBC_DEQUANT_LONG_SCALED_OFFSET 1555931970
#endif
#ifndef SBC_DEQUANT_LONG_UNSCALED_OFFSET
#define SBC_DEQUANT_LONG_UNSCALED_OFFSET 2147483648
#endif
#ifndef SBC_DEQUANT_SCALING_FACTOR
#define SBC_DEQUANT_SCALING_FACTOR 1.38019122262781f
#endif
extern const OI_UINT32 dequant_long_scaled[17];
extern const OI_UINT32 dequant_long_unscaled[17];
/** Scales x by y bits to the right, adding a rounding factor.
*/
#ifndef SCALE
#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y))
#endif
#ifdef DEBUG_DEQUANTIZATION
#include <math.h>
INLINE float dequant_float(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
float result = (1 << (scale_factor+1)) * ((raw * 2.0f + 1.0f) / ((1 << bits) - 1.0f) - 1.0f);
result /= SBC_DEQUANT_SCALING_FACTOR;
/* Unless the encoder screwed up, all correct dequantized values should
* satisfy this inequality. Non-compliant encoders which generate quantized
* values with all 1-bits set can, theoretically, trigger this assert. This
* is unlikely, however, and only an issue in debug mode.
*/
OI_ASSERT(fabs(result) < 32768 * 1.6);
return result;
}
#endif
INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
OI_UINT32 d;
OI_INT32 result;
OI_ASSERT(scale_factor <= 15);
OI_ASSERT(bits <= 16);
if (bits <= 1) {
return 0;
}
d = (raw * 2) + 1;
d *= dequant_long_scaled[bits];
result = d - SBC_DEQUANT_LONG_SCALED_OFFSET;
#ifdef DEBUG_DEQUANTIZATION
{
OI_INT32 integerized_float_result;
float float_result;
float_result = dequant_float(raw, scale_factor, bits);
integerized_float_result = (OI_INT32)floor(0.5f+float_result * (1 << 15));
/* This detects overflow */
OI_ASSERT(((result >= 0) && (integerized_float_result >= 0)) ||
((result <= 0) && (integerized_float_result <= 0)));
}
#endif
return result >> (15 - scale_factor);
}
/* This version of Dequant does not incorporate the scaling factor of 1.38. It
* is intended for use with implementations of the filterbank which are
* hard-coded into a DSP. Output is Q16.4 format, so that after joint stereo
* processing (which leaves the most significant bit equal to the sign bit if
* the encoder is conformant) the result will fit a 24 bit fixed point signed
* value.*/
INLINE OI_INT32 OI_SBC_Dequant_Unscaled(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits);
INLINE OI_INT32 OI_SBC_Dequant_Unscaled(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
OI_UINT32 d;
OI_INT32 result;
OI_ASSERT(scale_factor <= 15);
OI_ASSERT(bits <= 16);
if (bits <= 1) {
return 0;
}
if (bits == 16) {
result = (raw << 16) + raw - 0x7fff7fff;
return SCALE(result, 24 - scale_factor);
}
d = (raw * 2) + 1;
d *= dequant_long_unscaled[bits];
result = d - 0x80000000;
return SCALE(result, 24 - scale_factor);
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Dequantizer for SBC decoder; reconstructs quantized representation of subband samples.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
/**
This function is a fixed-point approximation of a modification of the following
dequantization operation defined in the spec, as inferred from section 12.6.4:
@code
dequant = 2^(scale_factor+1) * ((raw * 2.0 + 1.0) / ((2^bits) - 1) - 1)
2 <= bits <= 16
0 <= raw < (2^bits)-1 (the -1 is because quantized values with all 1's are forbidden)
-65535 < dequant < 65535
@endcode
The code below computes the dequantized value divided by a scaling constant
equal to about 1.38. This constant is chosen to ensure that the entry in the
dequant_long_scaled table for 16 bits is as accurate as possible, since it has
the least relative precision available to it due to its small magnitude.
This routine outputs in Q16.15 format.
The helper array dequant_long is defined as follows:
@code
dequant_long_long[bits] = round(2^31 * 1/((2^bits - 1) / 1.38...) for 2 <= bits <= 16
@endcode
Additionally, the table entries have the following property:
@code
dequant_long_scaled[bits] <= 2^31 / ((2^bits - 1)) for 2 <= bits <= 16
@endcode
Therefore
@code
d = 2 * raw + 1 1 <= d <= 2^bits - 2
d' = d * dequant_long[bits]
d * dequant_long_scaled[bits] <= (2^bits - 2) * (2^31 / (2^bits - 1))
d * dequant_long_scaled[bits] <= 2^31 * (2^bits - 2)/(2^bits - 1) < 2^31
@endcode
Therefore, d' doesn't overflow a signed 32-bit value.
@code
d' =~ 2^31 * (raw * 2.0 + 1.0) / (2^bits - 1) / 1.38...
result = d' - 2^31/1.38... =~ 2^31 * ((raw * 2.0 + 1.0) / (2^bits - 1) - 1) / 1.38...
result is therefore a scaled approximation to dequant. It remains only to
turn 2^31 into 2^(scale_factor+1). Since we're aiming for Q16.15 format,
this is achieved by shifting right by (15-scale_factor):
(2^31 * x) >> (15-scale_factor) =~ 2^(31-15+scale_factor) * x = 2^15 * 2^(1+scale_factor) * x
@endcode
*/
#include <oi_codec_sbc_private.h>
#ifndef SBC_DEQUANT_LONG_SCALED_OFFSET
#define SBC_DEQUANT_LONG_SCALED_OFFSET 1555931970
#endif
#ifndef SBC_DEQUANT_LONG_UNSCALED_OFFSET
#define SBC_DEQUANT_LONG_UNSCALED_OFFSET 2147483648
#endif
#ifndef SBC_DEQUANT_SCALING_FACTOR
#define SBC_DEQUANT_SCALING_FACTOR 1.38019122262781f
#endif
extern const OI_UINT32 dequant_long_scaled[17];
extern const OI_UINT32 dequant_long_unscaled[17];
/** Scales x by y bits to the right, adding a rounding factor.
*/
#ifndef SCALE
#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y))
#endif
#ifdef DEBUG_DEQUANTIZATION
#include <math.h>
INLINE float dequant_float(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
float result = (1 << (scale_factor+1)) * ((raw * 2.0f + 1.0f) / ((1 << bits) - 1.0f) - 1.0f);
result /= SBC_DEQUANT_SCALING_FACTOR;
/* Unless the encoder screwed up, all correct dequantized values should
* satisfy this inequality. Non-compliant encoders which generate quantized
* values with all 1-bits set can, theoretically, trigger this assert. This
* is unlikely, however, and only an issue in debug mode.
*/
OI_ASSERT(fabs(result) < 32768 * 1.6);
return result;
}
#endif
INLINE OI_INT32 OI_SBC_Dequant(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
OI_UINT32 d;
OI_INT32 result;
OI_ASSERT(scale_factor <= 15);
OI_ASSERT(bits <= 16);
if (bits <= 1) {
return 0;
}
d = (raw * 2) + 1;
d *= dequant_long_scaled[bits];
result = d - SBC_DEQUANT_LONG_SCALED_OFFSET;
#ifdef DEBUG_DEQUANTIZATION
{
OI_INT32 integerized_float_result;
float float_result;
float_result = dequant_float(raw, scale_factor, bits);
integerized_float_result = (OI_INT32)floor(0.5f+float_result * (1 << 15));
/* This detects overflow */
OI_ASSERT(((result >= 0) && (integerized_float_result >= 0)) ||
((result <= 0) && (integerized_float_result <= 0)));
}
#endif
return result >> (15 - scale_factor);
}
/* This version of Dequant does not incorporate the scaling factor of 1.38. It
* is intended for use with implementations of the filterbank which are
* hard-coded into a DSP. Output is Q16.4 format, so that after joint stereo
* processing (which leaves the most significant bit equal to the sign bit if
* the encoder is conformant) the result will fit a 24 bit fixed point signed
* value.*/
INLINE OI_INT32 OI_SBC_Dequant_Unscaled(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits);
INLINE OI_INT32 OI_SBC_Dequant_Unscaled(OI_UINT32 raw, OI_UINT scale_factor, OI_UINT bits)
{
OI_UINT32 d;
OI_INT32 result;
OI_ASSERT(scale_factor <= 15);
OI_ASSERT(bits <= 16);
if (bits <= 1) {
return 0;
}
if (bits == 16) {
result = (raw << 16) + raw - 0x7fff7fff;
return SCALE(result, 24 - scale_factor);
}
d = (raw * 2) + 1;
d *= dequant_long_unscaled[bits];
result = d - 0x80000000;
return SCALE(result, 24 - scale_factor);
}
/**
@}
*/
+55 -55
View File
@@ -1,55 +1,55 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
#include "oi_codec_sbc_private.h"
const OI_CHAR* const OI_CODEC_SBC_FreqText[] = { "SBC_FREQ_16000", "SBC_FREQ_32000", "SBC_FREQ_44100", "SBC_FREQ_48000" };
const OI_CHAR* const OI_CODEC_SBC_ModeText[] = { "SBC_MONO", "SBC_DUAL_CHANNEL", "SBC_STEREO", "SBC_JOINT_STEREO" };
const OI_CHAR* const OI_CODEC_SBC_SubbandsText[] = { "SBC_SUBBANDS_4", "SBC_SUBBANDS_8" };
const OI_CHAR* const OI_CODEC_SBC_BlocksText[] = { "SBC_BLOCKS_4", "SBC_BLOCKS_8", "SBC_BLOCKS_12", "SBC_BLOCKS_16" };
const OI_CHAR* const OI_CODEC_SBC_AllocText[] = { "SBC_LOUDNESS", "SBC_SNR" };
#ifdef OI_DEBUG
#include <stdio.h>
void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo)
{
printf("SBC configuration\n");
printf(" enhanced: %s\n", frameInfo->enhanced ? "TRUE" : "FALSE");
printf(" frequency: %d\n", frameInfo->frequency);
printf(" subbands: %d\n", frameInfo->nrof_subbands);
printf(" blocks: %d\n", frameInfo->nrof_blocks);
printf(" channels: %d\n", frameInfo->nrof_channels);
printf(" mode: %s\n", OI_CODEC_SBC_ModeText[frameInfo->mode]);
printf(" alloc: %s\n", OI_CODEC_SBC_AllocText[frameInfo->alloc]);
printf(" bitpool: %d\n", frameInfo->bitpool);
}
#endif /* OI_DEBUG */
/**@}*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
#include "oi_codec_sbc_private.h"
const OI_CHAR* const OI_CODEC_SBC_FreqText[] = { "SBC_FREQ_16000", "SBC_FREQ_32000", "SBC_FREQ_44100", "SBC_FREQ_48000" };
const OI_CHAR* const OI_CODEC_SBC_ModeText[] = { "SBC_MONO", "SBC_DUAL_CHANNEL", "SBC_STEREO", "SBC_JOINT_STEREO" };
const OI_CHAR* const OI_CODEC_SBC_SubbandsText[] = { "SBC_SUBBANDS_4", "SBC_SUBBANDS_8" };
const OI_CHAR* const OI_CODEC_SBC_BlocksText[] = { "SBC_BLOCKS_4", "SBC_BLOCKS_8", "SBC_BLOCKS_12", "SBC_BLOCKS_16" };
const OI_CHAR* const OI_CODEC_SBC_AllocText[] = { "SBC_LOUDNESS", "SBC_SNR" };
#ifdef OI_DEBUG
#include <stdio.h>
void OI_CODEC_SBC_DumpConfig(OI_CODEC_SBC_FRAME_INFO *frameInfo)
{
printf("SBC configuration\n");
printf(" enhanced: %s\n", frameInfo->enhanced ? "TRUE" : "FALSE");
printf(" frequency: %d\n", frameInfo->frequency);
printf(" subbands: %d\n", frameInfo->nrof_subbands);
printf(" blocks: %d\n", frameInfo->nrof_blocks);
printf(" channels: %d\n", frameInfo->nrof_channels);
printf(" mode: %s\n", OI_CODEC_SBC_ModeText[frameInfo->mode]);
printf(" alloc: %s\n", OI_CODEC_SBC_AllocText[frameInfo->alloc]);
printf(" bitpool: %d\n", frameInfo->bitpool);
}
#endif /* OI_DEBUG */
/**@}*/
+278 -278
View File
@@ -1,278 +1,278 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Checksum and header-related functions.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_assert.h"
/* asdasd */
#define USE_NIBBLEWISE_CRC
/* #define PRINT_SAMPLES */
/* #define PRINT_SCALEFACTORS */
/* #define DEBUG_CRC */
/*
* CRC-8 table for X^8 + X^4 + X^3 + X^2 + 1; byte-wise lookup
*/
#ifdef USE_WIDE_CRC
/* Save space if a char is 16 bits, such as on the C54x */
const OI_BYTE crc8_wide[128] = {
0x001d, 0x3a27, 0x7469, 0x4e53, 0xe8f5, 0xd2cf, 0x9c81, 0xa6bb, 0xcdd0, 0xf7ea, 0xb9a4, 0x839e, 0x2538, 0x1f02, 0x514c, 0x6b76, 0x879a, 0xbda0, 0xf3ee, 0xc9d4, 0x6f72, 0x5548, 0x1b06, 0x213c, 0x4a57, 0x706d, 0x3e23, 0x0419, 0xa2bf, 0x9885, 0xd6cb, 0xecf1, 0x130e, 0x2934, 0x677a, 0x5d40, 0xfbe6, 0xc1dc, 0x8f92, 0xb5a8, 0xdec3, 0xe4f9, 0xaab7, 0x908d, 0x362b, 0x0c11, 0x425f, 0x7865, 0x9489, 0xaeb3, 0xe0fd, 0xdac7, 0x7c61, 0x465b, 0x0815, 0x322f, 0x5944, 0x637e, 0x2d30, 0x170a, 0xb1ac, 0x8b96, 0xc5d8, 0xffe2, 0x263b, 0x1c01, 0x524f, 0x6875, 0xced3, 0xf4e9, 0xbaa7, 0x809d, 0xebf6, 0xd1cc, 0x9f82, 0xa5b8, 0x031e, 0x3924, 0x776a, 0x4d50, 0xa1bc, 0x9b86, 0xd5c8, 0xeff2, 0x4954, 0x736e, 0x3d20, 0x071a, 0x6c71, 0x564b, 0x1805, 0x223f, 0x8499, 0xbea3, 0xf0ed, 0xcad7, 0x3528, 0x0f12, 0x415c, 0x7b66, 0xddc0, 0xe7fa, 0xa9b4, 0x938e, 0xf8e5, 0xc2df, 0x8c91, 0xb6ab, 0x100d, 0x2a37, 0x6479, 0x5e43, 0xb2af, 0x8895, 0xc6db, 0xfce1, 0x5a47, 0x607d, 0x2e33, 0x1409, 0x7f62, 0x4558, 0x0b16, 0x312c, 0x978a, 0xadb0, 0xe3fe, 0xd9c4,
};
#elif defined(USE_NIBBLEWISE_CRC)
const OI_BYTE crc8_narrow[16] = {
0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb
};
#else
const OI_BYTE crc8_narrow[256] = {
0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c, 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a, 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09, 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4
};
#endif
const OI_UINT32 dequant_long_scaled[17] = {
0,
0,
0x1ee9e116, /* bits=2 0.24151243 1/3 * (1/1.38019122262781) (0x00000008)*/
0x0d3fa99c, /* bits=3 0.10350533 1/7 * (1/1.38019122262781) (0x00000013)*/
0x062ec69e, /* bits=4 0.04830249 1/15 * (1/1.38019122262781) (0x00000029)*/
0x02fddbfa, /* bits=5 0.02337217 1/31 * (1/1.38019122262781) (0x00000055)*/
0x0178d9f5, /* bits=6 0.01150059 1/63 * (1/1.38019122262781) (0x000000ad)*/
0x00baf129, /* bits=7 0.00570502 1/127 * (1/1.38019122262781) (0x0000015e)*/
0x005d1abe, /* bits=8 0.00284132 1/255 * (1/1.38019122262781) (0x000002bf)*/
0x002e760d, /* bits=9 0.00141788 1/511 * (1/1.38019122262781) (0x00000582)*/
0x00173536, /* bits=10 0.00070825 1/1023 * (1/1.38019122262781) (0x00000b07)*/
0x000b9928, /* bits=11 0.00035395 1/2047 * (1/1.38019122262781) (0x00001612)*/
0x0005cc37, /* bits=12 0.00017693 1/4095 * (1/1.38019122262781) (0x00002c27)*/
0x0002e604, /* bits=13 0.00008846 1/8191 * (1/1.38019122262781) (0x00005852)*/
0x000172fc, /* bits=14 0.00004422 1/16383 * (1/1.38019122262781) (0x0000b0a7)*/
0x0000b97d, /* bits=15 0.00002211 1/32767 * (1/1.38019122262781) (0x00016150)*/
0x00005cbe, /* bits=16 0.00001106 1/65535 * (1/1.38019122262781) (0x0002c2a5)*/
};
const OI_UINT32 dequant_long_unscaled[17] = {
0,
0,
0x2aaaaaab, /* bits=2 0.33333333 1/3 (0x00000005)*/
0x12492492, /* bits=3 0.14285714 1/7 (0x0000000e)*/
0x08888889, /* bits=4 0.06666667 1/15 (0x0000001d)*/
0x04210842, /* bits=5 0.03225806 1/31 (0x0000003e)*/
0x02082082, /* bits=6 0.01587302 1/63 (0x0000007e)*/
0x01020408, /* bits=7 0.00787402 1/127 (0x000000fe)*/
0x00808081, /* bits=8 0.00392157 1/255 (0x000001fd)*/
0x00402010, /* bits=9 0.00195695 1/511 (0x000003fe)*/
0x00200802, /* bits=10 0.00097752 1/1023 (0x000007fe)*/
0x00100200, /* bits=11 0.00048852 1/2047 (0x00000ffe)*/
0x00080080, /* bits=12 0.00024420 1/4095 (0x00001ffe)*/
0x00040020, /* bits=13 0.00012209 1/8191 (0x00003ffe)*/
0x00020008, /* bits=14 0.00006104 1/16383 (0x00007ffe)*/
0x00010002, /* bits=15 0.00003052 1/32767 (0x0000fffe)*/
0x00008001, /* bits=16 0.00001526 1/65535 (0x0001fffc)*/
};
#if defined(OI_DEBUG) || defined(PRINT_SAMPLES) || defined(PRINT_SCALEFACTORS)
#include <stdio.h>
#endif
#ifdef USE_WIDE_CRC
INLINE OI_CHAR crc_iterate(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_CHAR crc_iterate(OI_UINT8 oldcrc, OI_UINT8 next)
{
OI_UINT crc;
OI_UINT idx;
idx = oldcrc^next;
crc = crc8_wide[idx >> 1];
if (idx%2) {
crc &= 0xff;
} else {
crc >>= 8;
}
return crc;
}
INLINE OI_CHAR crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_CHAR crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next)
{
OI_UINT crc;
OI_UINT idx;
idx = (oldcrc ^ next) >> 4;
crc = crc8_wide[idx>>1];
if (idx%2) {
crc &= 0xff;
} else {
crc >>= 8;
}
return (oldcrc << 4) ^ crc;
}
#else // USE_WIDE_CRC
INLINE OI_UINT8 crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next)
{
return (oldcrc << 4) ^ crc8_narrow[(oldcrc^next) >> 4];
}
#ifdef USE_NIBBLEWISE_CRC
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next)
{
crc = (crc << 4) ^ crc8_narrow[(crc^next) >> 4];
crc = (crc << 4) ^ crc8_narrow[((crc>>4)^next)&0xf];
return crc;
}
#else // USE_NIBBLEWISE_CRC
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next)
{
return crc8_narrow[crc^next];
}
#endif // USE_NIBBLEWISE_CRC
#endif // USE_WIDE_CRC
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum_mSBC(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data)
{
OI_UINT i;
OI_UINT8 crc = 0x0f;
/* Count is the number of whole bytes subject to CRC. Actually, it's one
* more than this number, because data[3] is the CRC field itself, which is
* explicitly skipped. Since crc_iterate (should be) inlined, it's cheaper
* spacewise to include the check in the loop. This shouldn't be much of a
* bottleneck routine in the first place. */
// 0 - syncword (skip)
// 1 - reserved
crc = crc_iterate(crc,frame->reserved_for_future_use[0]);
// 2 - reserved
crc = crc_iterate(crc,frame->reserved_for_future_use[1]);
// 3 - crc (skip)
// 4..7 - scale factors (8 x 4 bit = 4 byte)
for (i = 0; i < 4; i++) {
crc = crc_iterate(crc,data[4+i]);
}
return crc;
}
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data)
{
OI_UINT i;
OI_UINT8 crc = 0x0f;
/* Count is the number of whole bytes subject to CRC. Actually, it's one
* more than this number, because data[3] is the CRC field itself, which is
* explicitly skipped. Since crc_iterate (should be) inlined, it's cheaper
* spacewise to include the check in the loop. This shouldn't be much of a
* bottleneck routine in the first place. */
OI_UINT count = (frame->nrof_subbands * frame->nrof_channels / 2u) + 4;
if ((frame->mode == SBC_JOINT_STEREO) && (frame->nrof_subbands == 8)) {
count++;
}
for (i = 1; i < count; i++) {
if (i != 3) {
crc = crc_iterate(crc,data[i]);
}
}
if ((frame->mode == SBC_JOINT_STEREO) && (frame->nrof_subbands == 4)) {
crc = crc_iterate_top4(crc, data[i]);
}
return crc;
}
void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame)
{
frame->nrof_blocks = block_values[frame->blocks];
frame->nrof_subbands = band_values[frame->subbands];
frame->frequency = freq_values[frame->freqIndex];
frame->nrof_channels = channel_values[frame->mode];
}
/**
* Unrolled macro to copy 4 32-bit aligned 32-bit values backward in memory
*/
#define COPY4WORDS_BACK(_dest, _src) \
do { \
OI_INT32 _a, _b, _c, _d; \
_a = *--_src; \
_b = *--_src; \
_c = *--_src; \
_d = *--_src; \
*--_dest = _a; \
*--_dest = _b; \
*--_dest = _c; \
*--_dest = _d; \
} while (0)
#if defined(USE_PLATFORM_MEMMOVE) || defined(USE_PLATFORM_MEMCPY)
#include <string.h>
#endif
PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount)
{
#ifdef USE_PLATFORM_MEMMOVE
memmove(dest, src, wordCount * sizeof(SBC_BUFFER_T));
#elif defined(USE_PLATFORM_MEMCPY)
OI_ASSERT(((OI_CHAR *)(dest) - (OI_CHAR *)(src)) >= wordCount*sizeof(*dest));
memcpy(dest, src, wordCount * sizeof(SBC_BUFFER_T));
#else
OI_UINT n;
OI_INT32 *d;
OI_INT32 *s;
n = wordCount / 4 / (sizeof(OI_INT32)/sizeof(*dest));
OI_ASSERT((n * 4 * (sizeof(OI_INT32)/sizeof(*dest))) == wordCount);
d = (OI_INT32*)(dest + wordCount);
s = (OI_INT32*)(src + wordCount);
do {
COPY4WORDS_BACK(d, s);
} while (--n);
#endif
}
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/**
@file
Checksum and header-related functions.
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
#include "oi_codec_sbc_private.h"
#include "oi_assert.h"
/* asdasd */
#define USE_NIBBLEWISE_CRC
/* #define PRINT_SAMPLES */
/* #define PRINT_SCALEFACTORS */
/* #define DEBUG_CRC */
/*
* CRC-8 table for X^8 + X^4 + X^3 + X^2 + 1; byte-wise lookup
*/
#ifdef USE_WIDE_CRC
/* Save space if a char is 16 bits, such as on the C54x */
const OI_BYTE crc8_wide[128] = {
0x001d, 0x3a27, 0x7469, 0x4e53, 0xe8f5, 0xd2cf, 0x9c81, 0xa6bb, 0xcdd0, 0xf7ea, 0xb9a4, 0x839e, 0x2538, 0x1f02, 0x514c, 0x6b76, 0x879a, 0xbda0, 0xf3ee, 0xc9d4, 0x6f72, 0x5548, 0x1b06, 0x213c, 0x4a57, 0x706d, 0x3e23, 0x0419, 0xa2bf, 0x9885, 0xd6cb, 0xecf1, 0x130e, 0x2934, 0x677a, 0x5d40, 0xfbe6, 0xc1dc, 0x8f92, 0xb5a8, 0xdec3, 0xe4f9, 0xaab7, 0x908d, 0x362b, 0x0c11, 0x425f, 0x7865, 0x9489, 0xaeb3, 0xe0fd, 0xdac7, 0x7c61, 0x465b, 0x0815, 0x322f, 0x5944, 0x637e, 0x2d30, 0x170a, 0xb1ac, 0x8b96, 0xc5d8, 0xffe2, 0x263b, 0x1c01, 0x524f, 0x6875, 0xced3, 0xf4e9, 0xbaa7, 0x809d, 0xebf6, 0xd1cc, 0x9f82, 0xa5b8, 0x031e, 0x3924, 0x776a, 0x4d50, 0xa1bc, 0x9b86, 0xd5c8, 0xeff2, 0x4954, 0x736e, 0x3d20, 0x071a, 0x6c71, 0x564b, 0x1805, 0x223f, 0x8499, 0xbea3, 0xf0ed, 0xcad7, 0x3528, 0x0f12, 0x415c, 0x7b66, 0xddc0, 0xe7fa, 0xa9b4, 0x938e, 0xf8e5, 0xc2df, 0x8c91, 0xb6ab, 0x100d, 0x2a37, 0x6479, 0x5e43, 0xb2af, 0x8895, 0xc6db, 0xfce1, 0x5a47, 0x607d, 0x2e33, 0x1409, 0x7f62, 0x4558, 0x0b16, 0x312c, 0x978a, 0xadb0, 0xe3fe, 0xd9c4,
};
#elif defined(USE_NIBBLEWISE_CRC)
const OI_BYTE crc8_narrow[16] = {
0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb
};
#else
const OI_BYTE crc8_narrow[256] = {
0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c, 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a, 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09, 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4
};
#endif
const OI_UINT32 dequant_long_scaled[17] = {
0,
0,
0x1ee9e116, /* bits=2 0.24151243 1/3 * (1/1.38019122262781) (0x00000008)*/
0x0d3fa99c, /* bits=3 0.10350533 1/7 * (1/1.38019122262781) (0x00000013)*/
0x062ec69e, /* bits=4 0.04830249 1/15 * (1/1.38019122262781) (0x00000029)*/
0x02fddbfa, /* bits=5 0.02337217 1/31 * (1/1.38019122262781) (0x00000055)*/
0x0178d9f5, /* bits=6 0.01150059 1/63 * (1/1.38019122262781) (0x000000ad)*/
0x00baf129, /* bits=7 0.00570502 1/127 * (1/1.38019122262781) (0x0000015e)*/
0x005d1abe, /* bits=8 0.00284132 1/255 * (1/1.38019122262781) (0x000002bf)*/
0x002e760d, /* bits=9 0.00141788 1/511 * (1/1.38019122262781) (0x00000582)*/
0x00173536, /* bits=10 0.00070825 1/1023 * (1/1.38019122262781) (0x00000b07)*/
0x000b9928, /* bits=11 0.00035395 1/2047 * (1/1.38019122262781) (0x00001612)*/
0x0005cc37, /* bits=12 0.00017693 1/4095 * (1/1.38019122262781) (0x00002c27)*/
0x0002e604, /* bits=13 0.00008846 1/8191 * (1/1.38019122262781) (0x00005852)*/
0x000172fc, /* bits=14 0.00004422 1/16383 * (1/1.38019122262781) (0x0000b0a7)*/
0x0000b97d, /* bits=15 0.00002211 1/32767 * (1/1.38019122262781) (0x00016150)*/
0x00005cbe, /* bits=16 0.00001106 1/65535 * (1/1.38019122262781) (0x0002c2a5)*/
};
const OI_UINT32 dequant_long_unscaled[17] = {
0,
0,
0x2aaaaaab, /* bits=2 0.33333333 1/3 (0x00000005)*/
0x12492492, /* bits=3 0.14285714 1/7 (0x0000000e)*/
0x08888889, /* bits=4 0.06666667 1/15 (0x0000001d)*/
0x04210842, /* bits=5 0.03225806 1/31 (0x0000003e)*/
0x02082082, /* bits=6 0.01587302 1/63 (0x0000007e)*/
0x01020408, /* bits=7 0.00787402 1/127 (0x000000fe)*/
0x00808081, /* bits=8 0.00392157 1/255 (0x000001fd)*/
0x00402010, /* bits=9 0.00195695 1/511 (0x000003fe)*/
0x00200802, /* bits=10 0.00097752 1/1023 (0x000007fe)*/
0x00100200, /* bits=11 0.00048852 1/2047 (0x00000ffe)*/
0x00080080, /* bits=12 0.00024420 1/4095 (0x00001ffe)*/
0x00040020, /* bits=13 0.00012209 1/8191 (0x00003ffe)*/
0x00020008, /* bits=14 0.00006104 1/16383 (0x00007ffe)*/
0x00010002, /* bits=15 0.00003052 1/32767 (0x0000fffe)*/
0x00008001, /* bits=16 0.00001526 1/65535 (0x0001fffc)*/
};
#if defined(OI_DEBUG) || defined(PRINT_SAMPLES) || defined(PRINT_SCALEFACTORS)
#include <stdio.h>
#endif
#ifdef USE_WIDE_CRC
INLINE OI_CHAR crc_iterate(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_CHAR crc_iterate(OI_UINT8 oldcrc, OI_UINT8 next)
{
OI_UINT crc;
OI_UINT idx;
idx = oldcrc^next;
crc = crc8_wide[idx >> 1];
if (idx%2) {
crc &= 0xff;
} else {
crc >>= 8;
}
return crc;
}
INLINE OI_CHAR crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_CHAR crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next)
{
OI_UINT crc;
OI_UINT idx;
idx = (oldcrc ^ next) >> 4;
crc = crc8_wide[idx>>1];
if (idx%2) {
crc &= 0xff;
} else {
crc >>= 8;
}
return (oldcrc << 4) ^ crc;
}
#else // USE_WIDE_CRC
INLINE OI_UINT8 crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate_top4(OI_UINT8 oldcrc, OI_UINT8 next)
{
return (oldcrc << 4) ^ crc8_narrow[(oldcrc^next) >> 4];
}
#ifdef USE_NIBBLEWISE_CRC
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next)
{
crc = (crc << 4) ^ crc8_narrow[(crc^next) >> 4];
crc = (crc << 4) ^ crc8_narrow[((crc>>4)^next)&0xf];
return crc;
}
#else // USE_NIBBLEWISE_CRC
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next);
INLINE OI_UINT8 crc_iterate(OI_UINT8 crc, OI_UINT8 next)
{
return crc8_narrow[crc^next];
}
#endif // USE_NIBBLEWISE_CRC
#endif // USE_WIDE_CRC
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum_mSBC(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data)
{
OI_UINT i;
OI_UINT8 crc = 0x0f;
/* Count is the number of whole bytes subject to CRC. Actually, it's one
* more than this number, because data[3] is the CRC field itself, which is
* explicitly skipped. Since crc_iterate (should be) inlined, it's cheaper
* spacewise to include the check in the loop. This shouldn't be much of a
* bottleneck routine in the first place. */
// 0 - syncword (skip)
// 1 - reserved
crc = crc_iterate(crc,frame->reserved_for_future_use[0]);
// 2 - reserved
crc = crc_iterate(crc,frame->reserved_for_future_use[1]);
// 3 - crc (skip)
// 4..7 - scale factors (8 x 4 bit = 4 byte)
for (i = 0; i < 4; i++) {
crc = crc_iterate(crc,data[4+i]);
}
return crc;
}
PRIVATE OI_UINT8 OI_SBC_CalculateChecksum(OI_CODEC_SBC_FRAME_INFO *frame, OI_BYTE const *data)
{
OI_UINT i;
OI_UINT8 crc = 0x0f;
/* Count is the number of whole bytes subject to CRC. Actually, it's one
* more than this number, because data[3] is the CRC field itself, which is
* explicitly skipped. Since crc_iterate (should be) inlined, it's cheaper
* spacewise to include the check in the loop. This shouldn't be much of a
* bottleneck routine in the first place. */
OI_UINT count = (frame->nrof_subbands * frame->nrof_channels / 2u) + 4;
if ((frame->mode == SBC_JOINT_STEREO) && (frame->nrof_subbands == 8)) {
count++;
}
for (i = 1; i < count; i++) {
if (i != 3) {
crc = crc_iterate(crc,data[i]);
}
}
if ((frame->mode == SBC_JOINT_STEREO) && (frame->nrof_subbands == 4)) {
crc = crc_iterate_top4(crc, data[i]);
}
return crc;
}
void OI_SBC_ExpandFrameFields(OI_CODEC_SBC_FRAME_INFO *frame)
{
frame->nrof_blocks = block_values[frame->blocks];
frame->nrof_subbands = band_values[frame->subbands];
frame->frequency = freq_values[frame->freqIndex];
frame->nrof_channels = channel_values[frame->mode];
}
/**
* Unrolled macro to copy 4 32-bit aligned 32-bit values backward in memory
*/
#define COPY4WORDS_BACK(_dest, _src) \
do { \
OI_INT32 _a, _b, _c, _d; \
_a = *--_src; \
_b = *--_src; \
_c = *--_src; \
_d = *--_src; \
*--_dest = _a; \
*--_dest = _b; \
*--_dest = _c; \
*--_dest = _d; \
} while (0)
#if defined(USE_PLATFORM_MEMMOVE) || defined(USE_PLATFORM_MEMCPY)
#include <string.h>
#endif
PRIVATE void shift_buffer(SBC_BUFFER_T *dest, SBC_BUFFER_T *src, OI_UINT wordCount)
{
#ifdef USE_PLATFORM_MEMMOVE
memmove(dest, src, wordCount * sizeof(SBC_BUFFER_T));
#elif defined(USE_PLATFORM_MEMCPY)
OI_ASSERT(((OI_CHAR *)(dest) - (OI_CHAR *)(src)) >= wordCount*sizeof(*dest));
memcpy(dest, src, wordCount * sizeof(SBC_BUFFER_T));
#else
OI_UINT n;
OI_INT32 *d;
OI_INT32 *s;
n = wordCount / 4 / (sizeof(OI_INT32)/sizeof(*dest));
OI_ASSERT((n * 4 * (sizeof(OI_INT32)/sizeof(*dest))) == wordCount);
d = (OI_INT32*)(dest + wordCount);
s = (OI_INT32*)(src + wordCount);
do {
COPY4WORDS_BACK(d, s);
} while (--n);
#endif
}
/**
@}
*/
+57 -57
View File
@@ -1,57 +1,57 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**
@file
This file contains a single function, which returns a string indicating the
version number of the eSBC codec
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
#include "oi_codec_sbc_private.h"
/** Version string for the BLUEmagic 3.0 protocol stack and profiles */
PRIVATE const OI_CHAR * codecVersion = "v1.5"
#ifdef OI_SBC_EVAL
" (Evaluation version)"
#endif
;
/** This function returns the version string for the BLUEmagic 3.0 protocol stack
and profiles */
const OI_CHAR *OI_CODEC_Version(void) {
return codecVersion;
}
/**********************************************************************************/
/**
@}
*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2002 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**
@file
This file contains a single function, which returns a string indicating the
version number of the eSBC codec
@ingroup codec_internal
*/
/**
@addtogroup codec_internal
@{
*/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
#include "oi_stddefs.h"
#include "oi_codec_sbc_private.h"
/** Version string for the BLUEmagic 3.0 protocol stack and profiles */
PRIVATE const OI_CHAR * codecVersion = "v1.5"
#ifdef OI_SBC_EVAL
" (Evaluation version)"
#endif
;
/** This function returns the version string for the BLUEmagic 3.0 protocol stack
and profiles */
const OI_CHAR *OI_CODEC_Version(void) {
return codecVersion;
}
/**********************************************************************************/
/**
@}
*/
+111 -111
View File
@@ -1,111 +1,111 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/*******************************************************************************
* @file readsamplesjoint.inc
*
* This is the body of the generic version of OI_SBC_ReadSamplesJoint().
* It is designed to be \#included into a function as follows:
\code
void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 4
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 8
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
\endcode
* Or to make a generic version:
\code
void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
#define NROF_SUBBANDS nrof_subbands
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
\endcode
* @ingroup codec_internal
*******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT bl = common->frameInfo.nrof_blocks;
OI_INT32 * RESTRICT s = common->subdata;
OI_UINT8 *ptr = global_bs->ptr.w;
OI_UINT32 value = global_bs->value;
OI_UINT bitPtr = global_bs->bitPtr;
OI_UINT8 jmask = common->frameInfo.join << (8 - NROF_SUBBANDS);
do {
OI_INT8 *sf_array = &common->scale_factor[0];
OI_UINT8 *bits_array = &common->bits.uint8[0];
OI_UINT8 joint = jmask;
OI_UINT sb;
/*
* Left channel
*/
sb = NROF_SUBBANDS;
do {
OI_UINT32 raw;
OI_INT32 dequant;
OI_UINT8 bits = *bits_array++;
OI_INT sf = *sf_array++;
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
dequant = OI_SBC_Dequant(raw, sf, bits);
*s++ = dequant;
} while (--sb);
/*
* Right channel
*/
sb = NROF_SUBBANDS;
do {
OI_UINT32 raw;
OI_INT32 dequant;
OI_UINT8 bits = *bits_array++;
OI_INT sf = *sf_array++;
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
dequant = OI_SBC_Dequant(raw, sf, bits);
/*
* Check if we need to do mid/side
*/
if (joint & 0x80) {
OI_INT32 mid = *(s - NROF_SUBBANDS);
OI_INT32 side = dequant;
*(s - NROF_SUBBANDS) = mid + side;
dequant = mid - side;
}
joint <<= 1;
*s++ = dequant;
} while (--sb);
} while (--bl);
}
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/*******************************************************************************
* @file readsamplesjoint.inc
*
* This is the body of the generic version of OI_SBC_ReadSamplesJoint().
* It is designed to be \#included into a function as follows:
\code
void OI_SBC_ReadSamplesJoint4(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 4
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
void OI_SBC_ReadSamplesJoint8(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
#define NROF_SUBBANDS 8
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
\endcode
* Or to make a generic version:
\code
void OI_SBC_ReadSamplesJoint(OI_CODEC_SBC_COMMON_CONTEXT *common, OI_BITSTREAM *global_bs)
{
OI_UINT nrof_subbands = common->frameInfo.nrof_subbands;
#define NROF_SUBBANDS nrof_subbands
#include "readsamplesjoint.inc"
#undef NROF_SUBBANDS
}
\endcode
* @ingroup codec_internal
*******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
{
OI_CODEC_SBC_COMMON_CONTEXT *common = &context->common;
OI_UINT bl = common->frameInfo.nrof_blocks;
OI_INT32 * RESTRICT s = common->subdata;
OI_UINT8 *ptr = global_bs->ptr.w;
OI_UINT32 value = global_bs->value;
OI_UINT bitPtr = global_bs->bitPtr;
OI_UINT8 jmask = common->frameInfo.join << (8 - NROF_SUBBANDS);
do {
OI_INT8 *sf_array = &common->scale_factor[0];
OI_UINT8 *bits_array = &common->bits.uint8[0];
OI_UINT8 joint = jmask;
OI_UINT sb;
/*
* Left channel
*/
sb = NROF_SUBBANDS;
do {
OI_UINT32 raw;
OI_INT32 dequant;
OI_UINT8 bits = *bits_array++;
OI_INT sf = *sf_array++;
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
dequant = OI_SBC_Dequant(raw, sf, bits);
*s++ = dequant;
} while (--sb);
/*
* Right channel
*/
sb = NROF_SUBBANDS;
do {
OI_UINT32 raw;
OI_INT32 dequant;
OI_UINT8 bits = *bits_array++;
OI_INT sf = *sf_array++;
OI_BITSTREAM_READUINT(raw, bits, ptr, value, bitPtr);
dequant = OI_SBC_Dequant(raw, sf, bits);
/*
* Check if we need to do mid/side
*/
if (joint & 0x80) {
OI_INT32 mid = *(s - NROF_SUBBANDS);
OI_INT32 side = dequant;
*(s - NROF_SUBBANDS) = mid + side;
dequant = mid - side;
}
joint <<= 1;
*s++ = dequant;
} while (--sb);
} while (--bl);
}
+136 -136
View File
@@ -1,136 +1,136 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**
@file
DO NOT EDIT THIS FILE DIRECTLY
This file is automatically generated by the "synthesis-gen.pl" script.
Any changes to this generated file will be lost when the script is re-run.
These functions are called by functions in synthesis.c to perform the synthesis
filterbank computations for the SBC decoder.
*/
#include <oi_codec_sbc_private.h>
#ifndef CLIP_INT16
#define CLIP_INT16(x) do { if (x > OI_INT16_MAX) { x = OI_INT16_MAX; } else if (x < OI_INT16_MIN) { x = OI_INT16_MIN; } } while (0)
#endif
#define MUL_16S_16S(_x, _y) ((_x) * (_y))
PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift);
PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift)
{
OI_INT32 pcm_a, pcm_b;
/* 1 - stage 0 */ pcm_b = 0;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 12]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-23167, buffer[ 20]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 28]))>> 2;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-17397, buffer[ 36]))<< 1;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(9399, buffer[ 44]))<< 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(17397, buffer[ 52]))<< 1;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 60]))>> 2;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(23167, buffer[ 68]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 76]))>> 3;
/* 1 - stage 0 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(0<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 1 */ pcm_a = 0;
/* 1 - stage 1 */ pcm_b = 0;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-3263, buffer[ 5]))>> 5;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(9293, buffer[ 5]))>> 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(29293, buffer[ 11]))>> 5;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-6087, buffer[ 11]))>> 2;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-5229, buffer[ 21]));
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1247, buffer[ 21]))<< 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(30835, buffer[ 27]))>> 3;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-2893, buffer[ 27]))<< 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-27021, buffer[ 37]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(23671, buffer[ 37]))<< 2;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(31633, buffer[ 43]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(18055, buffer[ 43]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(17319, buffer[ 53]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(11537, buffer[ 53]))>> 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(26663, buffer[ 59]))>> 2;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1747, buffer[ 59]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(4555, buffer[ 69]))>> 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(685, buffer[ 69]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(12419, buffer[ 75]))>> 4;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(8721, buffer[ 75]))>> 7;
/* 1 - stage 1 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(1<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 1 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(7<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 2 */ pcm_a = 0;
/* 1 - stage 2 */ pcm_b = 0;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-10385, buffer[ 6]))>> 6;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(11167, buffer[ 6]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(24995, buffer[ 10]))>> 5;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-10337, buffer[ 10]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-309, buffer[ 22]))<< 4;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(1917, buffer[ 22]))<< 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9161, buffer[ 26]))>> 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-30605, buffer[ 26]))>> 1;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-23063, buffer[ 38]))<< 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8317, buffer[ 38]))<< 3;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(27561, buffer[ 42]))<< 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(9553, buffer[ 42]))<< 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(2309, buffer[ 54]))<< 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(22117, buffer[ 54]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(12705, buffer[ 58]))>> 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(16383, buffer[ 58]))>> 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(6239, buffer[ 70]))>> 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(7543, buffer[ 70]))>> 3;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9251, buffer[ 74]))>> 4;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8603, buffer[ 74]))>> 6;
/* 1 - stage 2 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(2<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 2 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(6<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 3 */ pcm_a = 0;
/* 1 - stage 3 */ pcm_b = 0;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-16457, buffer[ 7]))>> 6;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(16913, buffer[ 7]))>> 5;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(19083, buffer[ 9]))>> 5;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-8443, buffer[ 9]))>> 7;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-23641, buffer[ 23]))>> 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(3687, buffer[ 23]))<< 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-29015, buffer[ 25]))>> 4;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-301, buffer[ 25]))<< 5;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-12889, buffer[ 39]))<< 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(15447, buffer[ 39]))<< 2;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(6145, buffer[ 41]))<< 3;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(10255, buffer[ 41]))<< 2;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(24211, buffer[ 55]))>> 1;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-18233, buffer[ 55]))>> 3;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(23469, buffer[ 57]))>> 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(9405, buffer[ 57]))>> 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(21223, buffer[ 71]))>> 8;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(1499, buffer[ 71]))>> 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(26913, buffer[ 73]))>> 6;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(26189, buffer[ 73]))>> 7;
/* 1 - stage 3 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(3<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 3 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(5<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 4 */ pcm_a = 0;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10445, buffer[ 8]))>> 4;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(-5297, buffer[ 24]))<< 1;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(22299, buffer[ 40]))<< 2;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10603, buffer[ 56]));
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(9539, buffer[ 72]))>> 4;
/* 1 - stage 4 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(4<<strideShift)] = (OI_INT16)pcm_a;
}
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**
@file
DO NOT EDIT THIS FILE DIRECTLY
This file is automatically generated by the "synthesis-gen.pl" script.
Any changes to this generated file will be lost when the script is re-run.
These functions are called by functions in synthesis.c to perform the synthesis
filterbank computations for the SBC decoder.
*/
#include <oi_codec_sbc_private.h>
#ifndef CLIP_INT16
#define CLIP_INT16(x) do { if (x > OI_INT16_MAX) { x = OI_INT16_MAX; } else if (x < OI_INT16_MIN) { x = OI_INT16_MIN; } } while (0)
#endif
#define MUL_16S_16S(_x, _y) ((_x) * (_y))
PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift);
PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRICT buffer, OI_UINT strideShift)
{
OI_INT32 pcm_a, pcm_b;
/* 1 - stage 0 */ pcm_b = 0;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 12]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-23167, buffer[ 20]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 28]))>> 2;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(-17397, buffer[ 36]))<< 1;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(9399, buffer[ 44]))<< 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(17397, buffer[ 52]))<< 1;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 60]))>> 2;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(23167, buffer[ 68]))>> 3;
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 76]))>> 3;
/* 1 - stage 0 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(0<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 1 */ pcm_a = 0;
/* 1 - stage 1 */ pcm_b = 0;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-3263, buffer[ 5]))>> 5;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(9293, buffer[ 5]))>> 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(29293, buffer[ 11]))>> 5;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-6087, buffer[ 11]))>> 2;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-5229, buffer[ 21]));
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1247, buffer[ 21]))<< 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(30835, buffer[ 27]))>> 3;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(-2893, buffer[ 27]))<< 3;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-27021, buffer[ 37]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(23671, buffer[ 37]))<< 2;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(31633, buffer[ 43]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(18055, buffer[ 43]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(17319, buffer[ 53]))<< 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(11537, buffer[ 53]))>> 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(26663, buffer[ 59]))>> 2;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(1747, buffer[ 59]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(4555, buffer[ 69]))>> 1;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(685, buffer[ 69]))<< 1;
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(12419, buffer[ 75]))>> 4;
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(8721, buffer[ 75]))>> 7;
/* 1 - stage 1 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(1<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 1 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(7<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 2 */ pcm_a = 0;
/* 1 - stage 2 */ pcm_b = 0;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-10385, buffer[ 6]))>> 6;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(11167, buffer[ 6]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(24995, buffer[ 10]))>> 5;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-10337, buffer[ 10]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-309, buffer[ 22]))<< 4;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(1917, buffer[ 22]))<< 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9161, buffer[ 26]))>> 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(-30605, buffer[ 26]))>> 1;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-23063, buffer[ 38]))<< 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8317, buffer[ 38]))<< 3;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(27561, buffer[ 42]))<< 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(9553, buffer[ 42]))<< 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(2309, buffer[ 54]))<< 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(22117, buffer[ 54]))>> 4;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(12705, buffer[ 58]))>> 1;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(16383, buffer[ 58]))>> 2;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(6239, buffer[ 70]))>> 3;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(7543, buffer[ 70]))>> 3;
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9251, buffer[ 74]))>> 4;
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8603, buffer[ 74]))>> 6;
/* 1 - stage 2 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(2<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 2 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(6<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 3 */ pcm_a = 0;
/* 1 - stage 3 */ pcm_b = 0;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-16457, buffer[ 7]))>> 6;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(16913, buffer[ 7]))>> 5;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(19083, buffer[ 9]))>> 5;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-8443, buffer[ 9]))>> 7;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-23641, buffer[ 23]))>> 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(3687, buffer[ 23]))<< 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-29015, buffer[ 25]))>> 4;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-301, buffer[ 25]))<< 5;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-12889, buffer[ 39]))<< 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(15447, buffer[ 39]))<< 2;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(6145, buffer[ 41]))<< 3;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(10255, buffer[ 41]))<< 2;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(24211, buffer[ 55]))>> 1;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(-18233, buffer[ 55]))>> 3;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(23469, buffer[ 57]))>> 2;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(9405, buffer[ 57]))>> 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(21223, buffer[ 71]))>> 8;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(1499, buffer[ 71]))>> 1;
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(26913, buffer[ 73]))>> 6;
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(26189, buffer[ 73]))>> 7;
/* 1 - stage 3 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(3<<strideShift)] = (OI_INT16)pcm_a;
/* 1 - stage 3 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(5<<strideShift)] = (OI_INT16)pcm_b;
/* 1 - stage 4 */ pcm_a = 0;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10445, buffer[ 8]))>> 4;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(-5297, buffer[ 24]))<< 1;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(22299, buffer[ 40]))<< 2;
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10603, buffer[ 56]));
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(9539, buffer[ 72]))>> 4;
/* 1 - stage 4 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(4<<strideShift)] = (OI_INT16)pcm_a;
}
+307 -307
View File
@@ -1,307 +1,307 @@
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
/*
* Performs an 8-point Type-II scaled DCT using the Arai-Agui-Nakajima
* factorization. The scaling factors are folded into the windowing
* constants. 29 adds and 5 16x32 multiplies per 8 samples.
*/
#include "oi_codec_sbc_private.h"
#define AAN_C4_FIX (759250125)/* S1.30 759250125 0.707107*/
#define AAN_C6_FIX (410903207)/* S1.30 410903207 0.382683*/
#define AAN_Q0_FIX (581104888)/* S1.30 581104888 0.541196*/
#define AAN_Q1_FIX (1402911301)/* S1.30 1402911301 1.306563*/
/** Scales x by y bits to the right, adding a rounding factor.
*/
#ifndef SCALE
#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y))
#endif
/**
* Default C language implementation of a 32x32->32 multiply. This function may
* be replaced by a platform-specific version for speed.
*
* @param u A signed 32-bit multiplicand
* @param v A signed 32-bit multiplier
* @return A signed 32-bit value corresponding to the 32 most significant bits
* of the 64-bit product of u and v.
*/
INLINE OI_INT32 default_mul_32s_32s_hi(OI_INT32 u, OI_INT32 v);
INLINE OI_INT32 default_mul_32s_32s_hi(OI_INT32 u, OI_INT32 v)
{
OI_UINT32 u0, v0;
OI_INT32 u1, v1, w1, w2, t;
u0 = u & 0xFFFF; u1 = u >> 16;
v0 = v & 0xFFFF; v1 = v >> 16;
t = u0*v0;
t = (u1*v0) + ((OI_UINT32)t >> 16);
w1 = t & 0xFFFF;
w2 = t >> 16;
w1 = (u0*v1) + w1;
return (u1*v1) + w2 + (w1 >> 16);
}
#define MUL_32S_32S_HI(_x, _y) default_mul_32s_32s_hi(_x, _y)
#ifdef DEBUG_DCT
PRIVATE void float_dct2_8(float * RESTRICT out, OI_INT32 const *RESTRICT in)
{
#define FIX(x,bits) (((int)floor(0.5f+((x)*((float)(1<<bits)))))/((float)(1<<bits)))
#define FLOAT_BUTTERFLY(x,y) x += y; y = x - (y*2); OI_ASSERT(VALID_INT32(x)); OI_ASSERT(VALID_INT32(y));
#define FLOAT_MULT_DCT(K, sample) (FIX(K,20) * sample)
#define FLOAT_SCALE(x, y) (((x) / (double)(1 << (y))))
double L00,L01,L02,L03,L04,L05,L06,L07;
double L25;
double in0,in1,in2,in3;
double in4,in5,in6,in7;
in0 = FLOAT_SCALE(in[0], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in0));
in1 = FLOAT_SCALE(in[1], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in1));
in2 = FLOAT_SCALE(in[2], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in2));
in3 = FLOAT_SCALE(in[3], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in3));
in4 = FLOAT_SCALE(in[4], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in4));
in5 = FLOAT_SCALE(in[5], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in5));
in6 = FLOAT_SCALE(in[6], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in6));
in7 = FLOAT_SCALE(in[7], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in7));
L00 = (in0 + in7); OI_ASSERT(VALID_INT32(L00));
L01 = (in1 + in6); OI_ASSERT(VALID_INT32(L01));
L02 = (in2 + in5); OI_ASSERT(VALID_INT32(L02));
L03 = (in3 + in4); OI_ASSERT(VALID_INT32(L03));
L04 = (in3 - in4); OI_ASSERT(VALID_INT32(L04));
L05 = (in2 - in5); OI_ASSERT(VALID_INT32(L05));
L06 = (in1 - in6); OI_ASSERT(VALID_INT32(L06));
L07 = (in0 - in7); OI_ASSERT(VALID_INT32(L07));
FLOAT_BUTTERFLY(L00, L03);
FLOAT_BUTTERFLY(L01, L02);
L02 += L03; OI_ASSERT(VALID_INT32(L02));
L02 = FLOAT_MULT_DCT(AAN_C4_FLOAT, L02); OI_ASSERT(VALID_INT32(L02));
FLOAT_BUTTERFLY(L00, L01);
out[0] = (float)FLOAT_SCALE(L00, DCTII_8_SHIFT_0); OI_ASSERT(VALID_INT16(out[0]));
out[4] = (float)FLOAT_SCALE(L01, DCTII_8_SHIFT_4); OI_ASSERT(VALID_INT16(out[4]));
FLOAT_BUTTERFLY(L03, L02);
out[6] = (float)FLOAT_SCALE(L02, DCTII_8_SHIFT_6); OI_ASSERT(VALID_INT16(out[6]));
out[2] = (float)FLOAT_SCALE(L03, DCTII_8_SHIFT_2); OI_ASSERT(VALID_INT16(out[2]));
L04 += L05; OI_ASSERT(VALID_INT32(L04));
L05 += L06; OI_ASSERT(VALID_INT32(L05));
L06 += L07; OI_ASSERT(VALID_INT32(L06));
L04/=2;
L05/=2;
L06/=2;
L07/=2;
L05 = FLOAT_MULT_DCT(AAN_C4_FLOAT, L05); OI_ASSERT(VALID_INT32(L05));
L25 = L06 - L04; OI_ASSERT(VALID_INT32(L25));
L25 = FLOAT_MULT_DCT(AAN_C6_FLOAT, L25); OI_ASSERT(VALID_INT32(L25));
L04 = FLOAT_MULT_DCT(AAN_Q0_FLOAT, L04); OI_ASSERT(VALID_INT32(L04));
L04 -= L25; OI_ASSERT(VALID_INT32(L04));
L06 = FLOAT_MULT_DCT(AAN_Q1_FLOAT, L06); OI_ASSERT(VALID_INT32(L06));
L06 -= L25; OI_ASSERT(VALID_INT32(L25));
FLOAT_BUTTERFLY(L07, L05);
FLOAT_BUTTERFLY(L05, L04);
out[3] = (float)(FLOAT_SCALE(L04, DCTII_8_SHIFT_3-1)); OI_ASSERT(VALID_INT16(out[3]));
out[5] = (float)(FLOAT_SCALE(L05, DCTII_8_SHIFT_5-1)); OI_ASSERT(VALID_INT16(out[5]));
FLOAT_BUTTERFLY(L07, L06);
out[7] = (float)(FLOAT_SCALE(L06, DCTII_8_SHIFT_7-1)); OI_ASSERT(VALID_INT16(out[7]));
out[1] = (float)(FLOAT_SCALE(L07, DCTII_8_SHIFT_1-1)); OI_ASSERT(VALID_INT16(out[1]));
}
#undef BUTTERFLY
#endif
/*
* This function calculates the AAN DCT. Its inputs are in S16.15 format, as
* returned by OI_SBC_Dequant. In practice, abs(in[x]) < 52429.0 / 1.38
* (1244918057 integer). The function it computes is an approximation to the array defined
* by:
*
* diag(aan_s) * AAN= C2
*
* or
*
* AAN = diag(1/aan_s) * C2
*
* where C2 is as it is defined in the comment at the head of this file, and
*
* aan_s[i] = aan_s = 1/(2*cos(i*pi/16)) with i = 1..7, aan_s[0] = 1;
*
* aan_s[i] = [ 1.000 0.510 0.541 0.601 0.707 0.900 1.307 2.563 ]
*
* The output ranges are shown as follows:
*
* Let Y[0..7] = AAN * X[0..7]
*
* Without loss of generality, assume the input vector X consists of elements
* between -1 and 1. The maximum possible value of a given output element occurs
* with some particular combination of input vector elements each of which is -1
* or 1. Consider the computation of Y[i]. Y[i] = sum t=0..7 of AAN[t,i]*X[i]. Y is
* maximized if the sign of X[i] matches the sign of AAN[t,i], ensuring a
* positive contribution to the sum. Equivalently, one may simply sum
* abs(AAN)[t,i] over t to get the maximum possible value of Y[i].
*
* This yields approximately [8.00 10.05 9.66 8.52 8.00 5.70 4.00 2.00]
*
* Given the maximum magnitude sensible input value of +/-37992, this yields the
* following vector of maximum output magnitudes:
*
* [ 303936 381820 367003 323692 303936 216555 151968 75984 ]
*
* Ultimately, these values must fit into 16 bit signed integers, so they must
* be scaled. A non-uniform scaling helps maximize the kept precision. The
* relative number of extra bits of precision maintainable with respect to the
* largest value is given here:
*
* [ 0 0 0 0 0 0 1 2 ]
*
*/
PRIVATE void dct2_8(SBC_BUFFER_T * RESTRICT out, OI_INT32 const *RESTRICT in);
PRIVATE void dct2_8(SBC_BUFFER_T * RESTRICT out, OI_INT32 const *RESTRICT in)
{
#define BUTTERFLY(x,y) x += y; y = x - (y<<1);
#define FIX_MULT_DCT(K, x) (MUL_32S_32S_HI(K,x)<<2)
OI_INT32 L00,L01,L02,L03,L04,L05,L06,L07;
OI_INT32 L25;
OI_INT32 in0,in1,in2,in3;
OI_INT32 in4,in5,in6,in7;
#if DCTII_8_SHIFT_IN != 0
in0 = SCALE(in[0], DCTII_8_SHIFT_IN);
in1 = SCALE(in[1], DCTII_8_SHIFT_IN);
in2 = SCALE(in[2], DCTII_8_SHIFT_IN);
in3 = SCALE(in[3], DCTII_8_SHIFT_IN);
in4 = SCALE(in[4], DCTII_8_SHIFT_IN);
in5 = SCALE(in[5], DCTII_8_SHIFT_IN);
in6 = SCALE(in[6], DCTII_8_SHIFT_IN);
in7 = SCALE(in[7], DCTII_8_SHIFT_IN);
#else
in0 = in[0];
in1 = in[1];
in2 = in[2];
in3 = in[3];
in4 = in[4];
in5 = in[5];
in6 = in[6];
in7 = in[7];
#endif
L00 = in0 + in7;
L01 = in1 + in6;
L02 = in2 + in5;
L03 = in3 + in4;
L04 = in3 - in4;
L05 = in2 - in5;
L06 = in1 - in6;
L07 = in0 - in7;
BUTTERFLY(L00, L03);
BUTTERFLY(L01, L02);
L02 += L03;
L02 = FIX_MULT_DCT(AAN_C4_FIX, L02);
BUTTERFLY(L00, L01);
out[0] = (OI_INT16)SCALE(L00, DCTII_8_SHIFT_0);
out[4] = (OI_INT16)SCALE(L01, DCTII_8_SHIFT_4);
BUTTERFLY(L03, L02);
out[6] = (OI_INT16)SCALE(L02, DCTII_8_SHIFT_6);
out[2] = (OI_INT16)SCALE(L03, DCTII_8_SHIFT_2);
L04 += L05;
L05 += L06;
L06 += L07;
L04/=2;
L05/=2;
L06/=2;
L07/=2;
L05 = FIX_MULT_DCT(AAN_C4_FIX, L05);
L25 = L06 - L04;
L25 = FIX_MULT_DCT(AAN_C6_FIX, L25);
L04 = FIX_MULT_DCT(AAN_Q0_FIX, L04);
L04 -= L25;
L06 = FIX_MULT_DCT(AAN_Q1_FIX, L06);
L06 -= L25;
BUTTERFLY(L07, L05);
BUTTERFLY(L05, L04);
out[3] = (OI_INT16)SCALE(L04, DCTII_8_SHIFT_3-1);
out[5] = (OI_INT16)SCALE(L05, DCTII_8_SHIFT_5-1);
BUTTERFLY(L07, L06);
out[7] = (OI_INT16)SCALE(L06, DCTII_8_SHIFT_7-1);
out[1] = (OI_INT16)SCALE(L07, DCTII_8_SHIFT_1-1);
#undef BUTTERFLY
#ifdef DEBUG_DCT
{
float float_out[8];
float_dct2_8(float_out, in);
}
#endif
}
/**@}*/
/******************************************************************************
*
* Copyright (C) 2014 The Android Open Source Project
* Copyright 2003 - 2004 Open Interface North America, Inc. All rights reserved.
*
* 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.
*
******************************************************************************/
/**********************************************************************************
$Revision: #1 $
***********************************************************************************/
/** @file
@ingroup codec_internal
*/
/**@addgroup codec_internal*/
/**@{*/
/*
* Performs an 8-point Type-II scaled DCT using the Arai-Agui-Nakajima
* factorization. The scaling factors are folded into the windowing
* constants. 29 adds and 5 16x32 multiplies per 8 samples.
*/
#include "oi_codec_sbc_private.h"
#define AAN_C4_FIX (759250125)/* S1.30 759250125 0.707107*/
#define AAN_C6_FIX (410903207)/* S1.30 410903207 0.382683*/
#define AAN_Q0_FIX (581104888)/* S1.30 581104888 0.541196*/
#define AAN_Q1_FIX (1402911301)/* S1.30 1402911301 1.306563*/
/** Scales x by y bits to the right, adding a rounding factor.
*/
#ifndef SCALE
#define SCALE(x, y) (((x) + (1 <<((y)-1))) >> (y))
#endif
/**
* Default C language implementation of a 32x32->32 multiply. This function may
* be replaced by a platform-specific version for speed.
*
* @param u A signed 32-bit multiplicand
* @param v A signed 32-bit multiplier
* @return A signed 32-bit value corresponding to the 32 most significant bits
* of the 64-bit product of u and v.
*/
INLINE OI_INT32 default_mul_32s_32s_hi(OI_INT32 u, OI_INT32 v);
INLINE OI_INT32 default_mul_32s_32s_hi(OI_INT32 u, OI_INT32 v)
{
OI_UINT32 u0, v0;
OI_INT32 u1, v1, w1, w2, t;
u0 = u & 0xFFFF; u1 = u >> 16;
v0 = v & 0xFFFF; v1 = v >> 16;
t = u0*v0;
t = (u1*v0) + ((OI_UINT32)t >> 16);
w1 = t & 0xFFFF;
w2 = t >> 16;
w1 = (u0*v1) + w1;
return (u1*v1) + w2 + (w1 >> 16);
}
#define MUL_32S_32S_HI(_x, _y) default_mul_32s_32s_hi(_x, _y)
#ifdef DEBUG_DCT
PRIVATE void float_dct2_8(float * RESTRICT out, OI_INT32 const *RESTRICT in)
{
#define FIX(x,bits) (((int)floor(0.5f+((x)*((float)(1<<bits)))))/((float)(1<<bits)))
#define FLOAT_BUTTERFLY(x,y) x += y; y = x - (y*2); OI_ASSERT(VALID_INT32(x)); OI_ASSERT(VALID_INT32(y));
#define FLOAT_MULT_DCT(K, sample) (FIX(K,20) * sample)
#define FLOAT_SCALE(x, y) (((x) / (double)(1 << (y))))
double L00,L01,L02,L03,L04,L05,L06,L07;
double L25;
double in0,in1,in2,in3;
double in4,in5,in6,in7;
in0 = FLOAT_SCALE(in[0], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in0));
in1 = FLOAT_SCALE(in[1], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in1));
in2 = FLOAT_SCALE(in[2], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in2));
in3 = FLOAT_SCALE(in[3], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in3));
in4 = FLOAT_SCALE(in[4], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in4));
in5 = FLOAT_SCALE(in[5], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in5));
in6 = FLOAT_SCALE(in[6], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in6));
in7 = FLOAT_SCALE(in[7], DCTII_8_SHIFT_IN); OI_ASSERT(VALID_INT32(in7));
L00 = (in0 + in7); OI_ASSERT(VALID_INT32(L00));
L01 = (in1 + in6); OI_ASSERT(VALID_INT32(L01));
L02 = (in2 + in5); OI_ASSERT(VALID_INT32(L02));
L03 = (in3 + in4); OI_ASSERT(VALID_INT32(L03));
L04 = (in3 - in4); OI_ASSERT(VALID_INT32(L04));
L05 = (in2 - in5); OI_ASSERT(VALID_INT32(L05));
L06 = (in1 - in6); OI_ASSERT(VALID_INT32(L06));
L07 = (in0 - in7); OI_ASSERT(VALID_INT32(L07));
FLOAT_BUTTERFLY(L00, L03);
FLOAT_BUTTERFLY(L01, L02);
L02 += L03; OI_ASSERT(VALID_INT32(L02));
L02 = FLOAT_MULT_DCT(AAN_C4_FLOAT, L02); OI_ASSERT(VALID_INT32(L02));
FLOAT_BUTTERFLY(L00, L01);
out[0] = (float)FLOAT_SCALE(L00, DCTII_8_SHIFT_0); OI_ASSERT(VALID_INT16(out[0]));
out[4] = (float)FLOAT_SCALE(L01, DCTII_8_SHIFT_4); OI_ASSERT(VALID_INT16(out[4]));
FLOAT_BUTTERFLY(L03, L02);
out[6] = (float)FLOAT_SCALE(L02, DCTII_8_SHIFT_6); OI_ASSERT(VALID_INT16(out[6]));
out[2] = (float)FLOAT_SCALE(L03, DCTII_8_SHIFT_2); OI_ASSERT(VALID_INT16(out[2]));
L04 += L05; OI_ASSERT(VALID_INT32(L04));
L05 += L06; OI_ASSERT(VALID_INT32(L05));
L06 += L07; OI_ASSERT(VALID_INT32(L06));
L04/=2;
L05/=2;
L06/=2;
L07/=2;
L05 = FLOAT_MULT_DCT(AAN_C4_FLOAT, L05); OI_ASSERT(VALID_INT32(L05));
L25 = L06 - L04; OI_ASSERT(VALID_INT32(L25));
L25 = FLOAT_MULT_DCT(AAN_C6_FLOAT, L25); OI_ASSERT(VALID_INT32(L25));
L04 = FLOAT_MULT_DCT(AAN_Q0_FLOAT, L04); OI_ASSERT(VALID_INT32(L04));
L04 -= L25; OI_ASSERT(VALID_INT32(L04));
L06 = FLOAT_MULT_DCT(AAN_Q1_FLOAT, L06); OI_ASSERT(VALID_INT32(L06));
L06 -= L25; OI_ASSERT(VALID_INT32(L25));
FLOAT_BUTTERFLY(L07, L05);
FLOAT_BUTTERFLY(L05, L04);
out[3] = (float)(FLOAT_SCALE(L04, DCTII_8_SHIFT_3-1)); OI_ASSERT(VALID_INT16(out[3]));
out[5] = (float)(FLOAT_SCALE(L05, DCTII_8_SHIFT_5-1)); OI_ASSERT(VALID_INT16(out[5]));
FLOAT_BUTTERFLY(L07, L06);
out[7] = (float)(FLOAT_SCALE(L06, DCTII_8_SHIFT_7-1)); OI_ASSERT(VALID_INT16(out[7]));
out[1] = (float)(FLOAT_SCALE(L07, DCTII_8_SHIFT_1-1)); OI_ASSERT(VALID_INT16(out[1]));
}
#undef BUTTERFLY
#endif
/*
* This function calculates the AAN DCT. Its inputs are in S16.15 format, as
* returned by OI_SBC_Dequant. In practice, abs(in[x]) < 52429.0 / 1.38
* (1244918057 integer). The function it computes is an approximation to the array defined
* by:
*
* diag(aan_s) * AAN= C2
*
* or
*
* AAN = diag(1/aan_s) * C2
*
* where C2 is as it is defined in the comment at the head of this file, and
*
* aan_s[i] = aan_s = 1/(2*cos(i*pi/16)) with i = 1..7, aan_s[0] = 1;
*
* aan_s[i] = [ 1.000 0.510 0.541 0.601 0.707 0.900 1.307 2.563 ]
*
* The output ranges are shown as follows:
*
* Let Y[0..7] = AAN * X[0..7]
*
* Without loss of generality, assume the input vector X consists of elements
* between -1 and 1. The maximum possible value of a given output element occurs
* with some particular combination of input vector elements each of which is -1
* or 1. Consider the computation of Y[i]. Y[i] = sum t=0..7 of AAN[t,i]*X[i]. Y is
* maximized if the sign of X[i] matches the sign of AAN[t,i], ensuring a
* positive contribution to the sum. Equivalently, one may simply sum
* abs(AAN)[t,i] over t to get the maximum possible value of Y[i].
*
* This yields approximately [8.00 10.05 9.66 8.52 8.00 5.70 4.00 2.00]
*
* Given the maximum magnitude sensible input value of +/-37992, this yields the
* following vector of maximum output magnitudes:
*
* [ 303936 381820 367003 323692 303936 216555 151968 75984 ]
*
* Ultimately, these values must fit into 16 bit signed integers, so they must
* be scaled. A non-uniform scaling helps maximize the kept precision. The
* relative number of extra bits of precision maintainable with respect to the
* largest value is given here:
*
* [ 0 0 0 0 0 0 1 2 ]
*
*/
PRIVATE void dct2_8(SBC_BUFFER_T * RESTRICT out, OI_INT32 const *RESTRICT in);
PRIVATE void dct2_8(SBC_BUFFER_T * RESTRICT out, OI_INT32 const *RESTRICT in)
{
#define BUTTERFLY(x,y) x += y; y = x - (y<<1);
#define FIX_MULT_DCT(K, x) (MUL_32S_32S_HI(K,x)<<2)
OI_INT32 L00,L01,L02,L03,L04,L05,L06,L07;
OI_INT32 L25;
OI_INT32 in0,in1,in2,in3;
OI_INT32 in4,in5,in6,in7;
#if DCTII_8_SHIFT_IN != 0
in0 = SCALE(in[0], DCTII_8_SHIFT_IN);
in1 = SCALE(in[1], DCTII_8_SHIFT_IN);
in2 = SCALE(in[2], DCTII_8_SHIFT_IN);
in3 = SCALE(in[3], DCTII_8_SHIFT_IN);
in4 = SCALE(in[4], DCTII_8_SHIFT_IN);
in5 = SCALE(in[5], DCTII_8_SHIFT_IN);
in6 = SCALE(in[6], DCTII_8_SHIFT_IN);
in7 = SCALE(in[7], DCTII_8_SHIFT_IN);
#else
in0 = in[0];
in1 = in[1];
in2 = in[2];
in3 = in[3];
in4 = in[4];
in5 = in[5];
in6 = in[6];
in7 = in[7];
#endif
L00 = in0 + in7;
L01 = in1 + in6;
L02 = in2 + in5;
L03 = in3 + in4;
L04 = in3 - in4;
L05 = in2 - in5;
L06 = in1 - in6;
L07 = in0 - in7;
BUTTERFLY(L00, L03);
BUTTERFLY(L01, L02);
L02 += L03;
L02 = FIX_MULT_DCT(AAN_C4_FIX, L02);
BUTTERFLY(L00, L01);
out[0] = (OI_INT16)SCALE(L00, DCTII_8_SHIFT_0);
out[4] = (OI_INT16)SCALE(L01, DCTII_8_SHIFT_4);
BUTTERFLY(L03, L02);
out[6] = (OI_INT16)SCALE(L02, DCTII_8_SHIFT_6);
out[2] = (OI_INT16)SCALE(L03, DCTII_8_SHIFT_2);
L04 += L05;
L05 += L06;
L06 += L07;
L04/=2;
L05/=2;
L06/=2;
L07/=2;
L05 = FIX_MULT_DCT(AAN_C4_FIX, L05);
L25 = L06 - L04;
L25 = FIX_MULT_DCT(AAN_C6_FIX, L25);
L04 = FIX_MULT_DCT(AAN_Q0_FIX, L04);
L04 -= L25;
L06 = FIX_MULT_DCT(AAN_Q1_FIX, L06);
L06 -= L25;
BUTTERFLY(L07, L05);
BUTTERFLY(L05, L04);
out[3] = (OI_INT16)SCALE(L04, DCTII_8_SHIFT_3-1);
out[5] = (OI_INT16)SCALE(L05, DCTII_8_SHIFT_5-1);
BUTTERFLY(L07, L06);
out[7] = (OI_INT16)SCALE(L06, DCTII_8_SHIFT_7-1);
out[1] = (OI_INT16)SCALE(L07, DCTII_8_SHIFT_1-1);
#undef BUTTERFLY
#ifdef DEBUG_DCT
{
float float_out[8];
float_dct2_8(float_out, in);
}
#endif
}
/**@}*/
File diff suppressed because it is too large Load Diff