summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp')
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp544
1 files changed, 544 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
new file mode 100644
index 0000000..873d7af
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
@@ -0,0 +1,544 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+ Pathname: ./audio/gsm-amr/c/src/amrdecode.c
+
+ Date: 05/23/2001
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: AMRDecode now doesn't call getbits() or put_header_in().
+ It also now obtains a new bit_offset value from a constant
+ rather than from the returned value of getbits().
+
+ Description: AMRDecode now returns byte_offset rather than bit_offset,
+ so the program can access the next frame that is byte
+ aligned rather than packed without padding.
+
+ Description: The structure types Speech_Decode_FrameState are now
+ passed into amrdecode( ) using void pointers, so that
+ higher level functions don't need to know anything about
+ this structure type.
+
+ Description: Changed input argument list. Added code to handle incoming DTX
+ frames, and added call to wmf_to_ets function prior to calling
+ GSMFrameDecode.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Changed all references to bit_offset to byte_offset.
+
+ Description: Added input_type to the function interface and modified code
+ to check type of conversion that needs to be made.
+
+ Description: Modified pseudo-code to include IF2 and ETS input formats.
+ Removed byte_offset from input list. Renamed speech_bits
+ to speech_bits_ptr.
+
+ Description: Added dec_input_format_tab.h in Include section. Modified
+ pseudo-code to use correct table names. Renamed input_type to
+ input_format and speech_bits to speech_bits_ptr.
+
+ Description: Removed *prev_mode_ptr in the input argument list.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Removed dec_input_format_tab.h from Include section.
+ 2. Changed type definition of raw_pcm_buffer in the I/O
+ definition section.
+
+ Description: Renamed WmfBytesPerFrame to WmfDecBytesPerFrame, and
+ If2BytesPerFrame to If2DecBytesPerFrame.
+
+ Description: Modified code so that the ETS testvectors could be fed directly
+ to this function.
+
+ Description: Changed '&' to '&&' in the setting of rx_type and mode for
+ AMR_SID < frame_type < NO_DATA case.
+
+ Description: Added code comments and made some code optimizations per Phase
+ 2/3 review comments.
+
+ Description: Added conditional compile around the call to GSMFrameDecode to
+ allow amrdecode.c to be used in the ETS reference console.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "amrdecode.h"
+#include "cnst.h"
+#include "typedef.h"
+#include "frame.h"
+#include "sp_dec.h"
+#include "wmf_to_ets.h"
+#include "if2_to_ets.h"
+#include "frame_type_3gpp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMRDecode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state_data = pointer to a structure (type void)
+
+ frame_type = 3GPP frame type (enum Frame_Type_3GPP)
+
+ speech_bits_ptr = pointer to the beginning of the raw encoded speech bits
+ for the current frame to be decoded (unsigned char)
+
+ raw_pcm_buffer = pointer to the output pcm outputs array (Word16)
+
+ input_format = input format used; valid values are AMR_WMF, AMR_IF2,
+ and AMR_ETS (Word16)
+
+ Outputs:
+ raw_pcm_buffer contains the newly decoded linear PCM speech samples
+ state_data->prev_mode contains the new mode
+
+ Returns:
+ byte_offset = address offset of the next frame to be processed or
+ error condition flag (-1) (int)
+
+ Global Variables Used:
+ WmfDecBytesPerFrame = table containing the number of core AMR data bytes
+ used by each codec mode for WMF input format (const
+ int)
+
+ If2DecBytesPerFrame = table containing the number of core AMR data bytes
+ used by each codec mode for IF2 input format (const
+ int)
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the top level entry function to the GSM AMR Decoder library.
+
+ First, it checks the input format type (input_format) to determine the type
+ of de-formattting that needs to be done. If input_format is AMR_WMF, the input
+ data is in WMF (aka, non-IF2) format and the function wmf_to_ets will be
+ called to convert to the ETS format (1 bit/word, where 1 word = 16 bits),
+ and byte_offset will be updated according to the contents of WmfDecBytesPerFrame
+ table.
+
+ If input_format is AMR_IF2, the input data is in IF2 format [1] and the
+ function if2_to_ets will be called to convert to the ETS format, and
+ byte_offset will be updated according to the contents of If2DecBytesPerFrame
+ table.
+
+ The codec mode and receive frame type is initialized based on the incoming
+ frame_type.
+
+ If input_format is AMR_ETS, the input data is in the ETS format. The receive
+ frame type is set to the value in the first location of the buffer pointed to
+ by speech_bits_ptr. Then, the encoded speech parameters in the buffer pointed
+ to by speech_bits is copied to dec_ets_input_bfr and the type will be changed
+ from unsigned char to Word16. Lastly, if the receive frame type is not
+ RX_NO_DATA, the mode is obtained from the buffer pointed to by
+ speech_bits_ptr, offset by MAX_SERIAL_SIZE+1, otherwise, the mode is set to
+ the previous mode (found the in state_data->prev_mode).
+
+ If input_format is an unsupported format, byte_offset will be set to -1, to
+ indicate an error condition has occurred, and the function will exit.
+
+ If there are no errors, GSMFrameDecode is called to decode a 20 ms frame. It
+ puts the decoded linear PCM samples in the buffer pointed to by
+ raw_pcm_buffer. Then, the prev_mode field of the structure pointed to by
+ state_data is updated to the current mode.
+
+ This function returns the new byte_offset value to indicate the address
+ offset of the next speech frame to be decoded.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] "AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0
+ Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: AMRSID_RXTYPE_BIT_OFFSET = 35
+ AMRSID_RXMODE_BIT_OFFSET = 36
+ NUM_AMRSID_RXMODE_BITS = 3
+
+
+ // Set up Decoder state structure pointer
+ Speech_Decode_FrameState *decoder_state
+ = (Speech_Decode_FrameState *) state_data
+
+ // Determine type of de-formatting
+
+ // Decode WMF or IF2 frames
+ IF ((input_format == AMR_RX_WMF) | (input_format == AMR_RX_IF2))
+ THEN
+ IF (input_format == AMR_RX_WMF)
+ THEN
+ // Convert incoming packetized raw WMF data to ETS format
+ CALL wmf_to_ets(frame_type = frame_type
+ input_ptr = speech_bits_ptr
+ output_ptr = &dec_ets_input_bfr)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Address offset of the start of next frame
+ byte_offset = WmfDecBytesPerFrame[frame_type]
+
+ ELSEIF (input_format == AMR_RX_IF2)
+ THEN
+ // Convert incoming packetized raw IF2 data to ETS format
+ CALL if2_to_ets(frame_type = frame_type
+ input_ptr = speech_bits_ptr
+ output_ptr = &dec_ets_input_bfr)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Address offset of the start of next frame
+ byte_offset = If2DecBytesPerFrame[frame_type]
+
+ ENDIF
+
+ // Determine AMR codec mode and AMR RX frame type
+ IF (frame_type <= AMR_122)
+ THEN
+ mode = (enum Mode) frame_type;
+ rx_type = RX_SPEECH_GOOD;
+
+ ELSEIF (frame_type == AMR_SID)
+ THEN
+ // Clear mode store prior to reading mode info from input buffer
+ mode = 0
+
+ FOR i = 0 TO NUM_AMRSID_RXMODE_BITS-1
+
+ mode |= (dec_ets_input_bfr[AMRSID_RXMODE_BIT_OFFSET+i] << i)
+
+ ENDFOR
+
+ IF (dec_ets_input_bfr[AMRSID_RXTYPE_BIT_OFFSET] == 0)
+ THEN
+ rx_type = RX_SID_FIRST
+
+ ELSE
+ rx_type = RX_SID_UPDATE
+
+ ENDIF
+
+ ELSEIF ((frame_type > AMR_SID) && (frame_type < NO_DATA))
+ THEN
+ // Use previous mode
+ mode = decoder_state->prev_mode
+
+ // Unsupported SID frames
+ rx_type = RX_SPEECH_BAD;
+
+ ELSE
+ // Use previous mode
+ mode = decoder_state->prev_mode
+
+ // No data received
+ rx_type = RX_NO_DATA;
+
+ ENDIF
+
+ // Decode ETS frames
+ ELSEIF (input_format == AMR_RX_ETS)
+ THEN
+ // Change type of pointer to incoming raw ETS data
+ ets_word_ptr = (Word16 *) speech_bits_ptr
+
+ // Get RX frame type
+ rx_type = (enum RXFrameType) *ets_word_ptr
+ ets_word_ptr = ets_word_ptr + 1
+
+ // Copy incoming raw ETS data to dec_ets_input_bfr
+ FOR i = 0 TO MAX_SERIAL_SIZE-1
+
+ dec_ets_input_bfr[i] = *ets_word_ptr
+ ets_word_ptr = ets_word_ptr + 1
+
+ ENDFOR
+
+ // Get codec mode
+ IF (rx_type != RX_NO_DATA)
+ THEN
+ mode = (enum Mode) *ets_word_ptr
+
+ ELSE
+ //Use previous mode if no received data
+ mode = decoder_state->prev_mode
+
+ ENDIF
+
+ // Set up byte_offset
+ byte_offset = 2*(MAX_SERIAL_SIZE+2)
+
+ ELSE
+ // Invalid format, return error code
+ byte_offset = -1
+
+ ENDIF
+
+ // Proceed with decoding frame, if there are no errors
+ IF (byte_offset != -1)
+ THEN
+ // Decode a 20 ms frame
+ CALL GSMFrameDecode( st = decoder_state
+ mode = mode
+ serial = dec_ets_input_bfr,
+ frame_type = rx_type,
+ synth = (Word16 *)raw_pcm_buffer);
+ MODIFYING (nothing)
+ RETURNING (Nothing)
+
+ // Save mode for next frame
+ decoder_state->prev_mode = mode
+
+ ENDIF
+
+ RETURN (byte_offset)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 AMRDecode(
+ void *state_data,
+ enum Frame_Type_3GPP frame_type,
+ UWord8 *speech_bits_ptr,
+ Word16 *raw_pcm_buffer,
+ bitstream_format input_format
+)
+{
+ Word16 *ets_word_ptr;
+ enum Mode mode = (enum Mode)MR475;
+ int modeStore;
+ int tempInt;
+ enum RXFrameType rx_type = RX_NO_DATA;
+ Word16 dec_ets_input_bfr[MAX_SERIAL_SIZE];
+ Word16 i;
+ Word16 byte_offset = -1;
+
+ /* Type cast state_data to Speech_Decode_FrameState rather than passing
+ * that structure type to this function so the structure make up can't
+ * be viewed from higher level functions than this.
+ */
+ Speech_Decode_FrameState *decoder_state
+ = (Speech_Decode_FrameState *) state_data;
+
+ /* Determine type of de-formatting */
+ /* WMF or IF2 frames */
+ if ((input_format == MIME_IETF) | (input_format == IF2))
+ {
+ if (input_format == MIME_IETF)
+ {
+ /* Convert incoming packetized raw WMF data to ETS format */
+ wmf_to_ets(frame_type, speech_bits_ptr, dec_ets_input_bfr);
+
+ /* Address offset of the start of next frame */
+ byte_offset = WmfDecBytesPerFrame[frame_type];
+ }
+ else /* else has to be input_format IF2 */
+ {
+ /* Convert incoming packetized raw IF2 data to ETS format */
+ if2_to_ets(frame_type, speech_bits_ptr, dec_ets_input_bfr);
+
+ /* Address offset of the start of next frame */
+ byte_offset = If2DecBytesPerFrame[frame_type];
+ }
+
+ /* At this point, input data is in ETS format */
+ /* Determine AMR codec mode and AMR RX frame type */
+ if (frame_type <= AMR_122)
+ {
+ mode = (enum Mode) frame_type;
+ rx_type = RX_SPEECH_GOOD;
+ }
+ else if (frame_type == AMR_SID)
+ {
+ /* Clear mode store prior to reading mode info from input buffer */
+ modeStore = 0;
+
+ for (i = 0; i < NUM_AMRSID_RXMODE_BITS; i++)
+ {
+ tempInt = dec_ets_input_bfr[AMRSID_RXMODE_BIT_OFFSET+i] << i;
+ modeStore |= tempInt;
+ }
+ mode = (enum Mode) modeStore;
+
+ /* Get RX frame type */
+ if (dec_ets_input_bfr[AMRSID_RXTYPE_BIT_OFFSET] == 0)
+ {
+ rx_type = RX_SID_FIRST;
+ }
+ else
+ {
+ rx_type = RX_SID_UPDATE;
+ }
+ }
+ else if (frame_type < AMR_NO_DATA)
+ {
+ /* Invalid frame_type, return error code */
+ byte_offset = -1; /* !!! */
+ }
+ else
+ {
+ mode = decoder_state->prev_mode;
+
+ /*
+ * RX_NO_DATA, generate exponential decay from latest valid frame for the first 6 frames
+ * after that, create silent frames
+ */
+ rx_type = RX_NO_DATA;
+
+ }
+
+ }
+
+ /* ETS frames */
+ else if (input_format == ETS)
+ {
+ /* Change type of pointer to incoming raw ETS data */
+ ets_word_ptr = (Word16 *) speech_bits_ptr;
+
+ /* Get RX frame type */
+ rx_type = (enum RXFrameType) * ets_word_ptr;
+ ets_word_ptr++;
+
+ /* Copy incoming raw ETS data to dec_ets_input_bfr */
+ for (i = 0; i < MAX_SERIAL_SIZE; i++)
+ {
+ dec_ets_input_bfr[i] = *ets_word_ptr;
+ ets_word_ptr++;
+ }
+
+ /* Get codec mode */
+ if (rx_type != RX_NO_DATA)
+ {
+ /* Get mode from input bitstream */
+ mode = (enum Mode) * ets_word_ptr;
+ }
+ else
+ {
+ /* Use previous mode if no received data */
+ mode = decoder_state->prev_mode;
+ }
+
+ /* Set up byte_offset */
+ byte_offset = 2 * (MAX_SERIAL_SIZE + 2);
+ }
+ else
+ {
+ /* Invalid input format, return error code */
+ byte_offset = -1;
+ }
+
+ /* Proceed with decoding frame, if there are no errors */
+ if (byte_offset != -1)
+ {
+ /* Decode a 20 ms frame */
+
+#ifndef CONSOLE_DECODER_REF
+ /* Use PV version of sp_dec.c */
+ GSMFrameDecode(decoder_state, mode, dec_ets_input_bfr, rx_type,
+ raw_pcm_buffer);
+
+#else
+ /* Use ETS version of sp_dec.c */
+ Speech_Decode_Frame(decoder_state, mode, dec_ets_input_bfr, rx_type,
+ raw_pcm_buffer);
+
+#endif
+
+ /* Save mode for next frame */
+ decoder_state->prev_mode = mode;
+ }
+
+ return (byte_offset);
+}
+
+
+