codec_decoder.asm
来自「bc5_stereo:bluetooth stereo Headset CODE」· 汇编 代码 · 共 729 行 · 第 1/2 页
ASM
729 行
// *****************************************************************************
// Copyright (C) Cambridge Silicon Radio plc 2003-2007 http://www.csr.com
// Part of Stereo-Headset-SDK Q1-2007.Release
//
// $Revision$ $Date$
// *****************************************************************************
// *****************************************************************************
// DESCRIPTION
// Decoder (SBC/MP3/AAC) for an audio playing device (non USB)
//
// *****************************************************************************
.ifndef SELECTED_CODEC_SBC
.ifndef SELECTED_CODEC_MP3
.ifndef SELECTED_CODEC_AAC
.define SELECTED_CODEC_SBC
.endif
.endif
.endif
// select the codec specific options
.ifdef SELECTED_CODEC_SBC
.define SELECTED_CODEC_FRAME_DECODE_FUNCTION &$sbcdec.frame_decode
.define SELECTED_CODEC_RESET_DECODER_FUNCTION &$sbcdec.reset_decoder
.define SELECTED_CODEC_SILENCE_DECODER_FUNCTION &$sbcdec.silence_decoder
.define SELECTED_CODEC_INITIALISE_DECODER_FUNCTION $sbcdec.init_decoder
.define SELECTED_CODEC_LIBRARY_HEADER "sbc_library.h"
.endif
.ifdef SELECTED_CODEC_MP3
.define SELECTED_CODEC_FRAME_DECODE_FUNCTION &$mp3dec.frame_decode
.define SELECTED_CODEC_RESET_DECODER_FUNCTION &$mp3dec.reset_decoder
.define SELECTED_CODEC_SILENCE_DECODER_FUNCTION &$mp3dec.silence_decoder
.define SELECTED_CODEC_INITIALISE_DECODER_FUNCTION $mp3dec.init_decoder
.define SELECTED_CODEC_LIBRARY_HEADER "mp3_library.h"
.endif
.ifdef SELECTED_CODEC_AAC
.define SELECTED_CODEC_FRAME_DECODE_FUNCTION &$aacdec.frame_decode
.define SELECTED_CODEC_RESET_DECODER_FUNCTION &$aacdec.reset_decoder
.define SELECTED_CODEC_SILENCE_DECODER_FUNCTION &$aacdec.silence_decoder
.define SELECTED_CODEC_INITIALISE_DECODER_FUNCTION $aacdec.init_decoder
.define SELECTED_CODEC_LIBRARY_HEADER "aac_library.h"
// At the moment BL does not ship with AAC support so we do not want to make
// kalprops.xml files for AAC. However we need to store default values
// somewhere. This seems the best place to put them as the makefiles will
// still remove them correctly. When AAC is supported these values will be
// exported to a kalprops.xml file.
.define AUDIO_CBUFFER_SIZE 2048
// codec buffer size as mp3: max range-3072, normal-1536, low latency-768
.define CODEC_CBUFFER_SIZE 3072
.define COMFORT_NOISE_GAIN 0
.define GOOD_WORKING_BUFFER_LEVEL 0.65
.define POORLINK_DETECT_LEVEL 0.5
.define POORLINK_PERIOD 1000000
.define ZERO_DATA_RATE_STOPPING 150000
.define ZERO_DATA_RATE_BUFFERING 200000
.define WARP_RATE_MAX_RAMP 0.008 // 0.8% per sec
.define WARP_RATE_HIGH_COEFFICIENT 0.015 // 1.5% per 1kb buffer diff
.define WARP_RATE_LOW_COEFFICIENT 0.002 // 0.2% per 1kb buffer diff
.define WARP_RATE_TRANSITION_LEVEL_WORDS 100 // use high coef if >100 words
.define WARP_FILTER_COEFS cbops.warp_and_shift.high_quality_filter_coefs
.define WARP_FILTER_LENGTH cbops.warp_and_shift.high_quality_filter_data_size
.endif
// 1.5ms is chosen as the interrupt rate for the audio input/output because:
// adc/dac mmu buffer is 256byte = 128samples
// - upto 8 sample fifo in voice interface
// = 120samples = 2.5ms @ 48KHz
// assume absolute worst case jitter on interrupts = 1.0ms
// Hence choose 1.5ms between audio input/output interrupts
.define TMR_PERIOD_AUDIO_COPY 1500
// 8ms is chosen as the interrupt rate for the codec input/output as this is a
// good compromise between not overloading the xap with messages and making
// sure that the xap side buffer is emptied relatively often.
.define TMR_PERIOD_CODEC_COPY 8000
// The timer period for copying tones. We don't want to force the VM to fill
// up the tone buffer too regularly.
.define TMR_PERIOD_TONE_COPY 10000
.CONST $TONE_BUFFER_SIZE 512;
// A debug define to force the decoder to use a mono output
//.define FORCE_MONO 1
// includes
.include "core_library.h"
.include "cbops_library.h"
.include "codec_library.h"
.include SELECTED_CODEC_LIBRARY_HEADER
.MODULE $M.main;
.CODESEGMENT PM;
.DATASEGMENT DM;
$main:
// ** setup ports that are to be used **
.CONST $AUDIO_LEFT_OUT_PORT ($cbuffer.WRITE_PORT_MASK + 0);
.CONST $AUDIO_RIGHT_OUT_PORT ($cbuffer.WRITE_PORT_MASK + 1);
.CONST $CODEC_IN_PORT ($cbuffer.READ_PORT_MASK + 0);
.CONST $TONE_IN_PORT (($cbuffer.READ_PORT_MASK | $cbuffer.FORCE_PCM_AUDIO) + 3);
// ** allocate memory for cbuffers **
.VAR/DMCIRC $audio_out_left[AUDIO_CBUFFER_SIZE];
.VAR/DMCIRC $audio_out_right[AUDIO_CBUFFER_SIZE];
.VAR/DMCIRC $audio_out_mix_left[AUDIO_CBUFFER_SIZE];
.VAR/DMCIRC $audio_out_mix_right[AUDIO_CBUFFER_SIZE];
.VAR/DMCIRC $codec_in[CODEC_CBUFFER_SIZE];
.VAR/DMCIRC $tone_in[$TONE_BUFFER_SIZE];
.VAR/DMCIRC $tone_resample_in[$TONE_BUFFER_SIZE];
// ** allocate memory for cbuffer structures **
.VAR $codec_in_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($codec_in), // size
&$codec_in, // read pointer
&$codec_in; // write pointer
.VAR $audio_out_left_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($audio_out_left), // size
&$audio_out_left, // read pointer
&$audio_out_left; // write pointer
.VAR $audio_out_right_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($audio_out_right), // size
&$audio_out_right, // read pointer
&$audio_out_right; // write pointer
.VAR $audio_out_mix_left_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($audio_out_mix_left), // size
&$audio_out_mix_left, // read pointer
&$audio_out_mix_left; // write pointer
.VAR $audio_out_mix_right_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($audio_out_mix_right), // size
&$audio_out_mix_right, // read pointer
&$audio_out_mix_right; // write pointer
.VAR $tone_in_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($tone_in), // size
&$tone_in, // read pointer
&$tone_in; // write pointer
.VAR $tone_resample_cbuffer_struc[$cbuffer.STRUC_SIZE] =
LENGTH($tone_resample_in), // size
&$tone_resample_in, // read pointer
&$tone_resample_in; // write pointer
// ** allocate memory for timer structures **
.VAR $codec_in_timer_struc[$timer.STRUC_SIZE];
.VAR $audio_out_timer_struc[$timer.STRUC_SIZE];
.VAR $tone_copy_timer_struc[$timer.STRUC_SIZE];
// ** allocate memory for codec input cbops copy routine **
.VAR $codec_in_copy_struc[] =
&$codec_in_copy_op, // first operator block
1, // number of inputs
$CODEC_IN_PORT, // input
1, // number of outputs
&$codec_in_cbuffer_struc; // output
.BLOCK $codec_in_copy_op;
.VAR $codec_in_copy_op.next = $cbops.NO_MORE_OPERATORS;
.VAR $codec_in_copy_op.func = &$cbops.copy_op;
.VAR $codec_in_copy_op.param[$cbops.copy_op.STRUC_SIZE] =
0, // Input index
1; // Output index
.ENDBLOCK;
// ** allocate memory for tone input cbops copy routine **
.VAR $tone_in_copy_struc[] =
&$tone_write_limit_op, /*&$tone_in_copy_op,*/ // first operator block
1, // number of inputs
$TONE_IN_PORT, // input
1, // number of outputs
&$tone_in_cbuffer_struc; // output
.BLOCK $tone_write_limit_op;
.VAR $tone_write_limit_op.next = &$tone_in_copy_op;
.VAR $tone_write_limit_op.func = &$cbops.limited_copy;
.VAR $tone_write_limit_op.mono[$cbops.limited_copy.STRUC_SIZE] =
$cbops.limited_copy.NO_READ_LIMIT,
50;
.ENDBLOCK;
.BLOCK $tone_in_copy_op;
.VAR $tone_in_copy_op.next = $cbops.NO_MORE_OPERATORS;
.VAR $tone_in_copy_op.func = &$cbops.shift;
.VAR $tone_in_copy_op.param[$cbops.shift.STRUC_SIZE] =
0, // Input index
1, // Output index
3;
.ENDBLOCK;
.VAR $tone_resample_copy_struc[] =
&$tone_resample_op,
1,
&$tone_in_cbuffer_struc,
1,
&$tone_resample_cbuffer_struc;
.BLOCK $tone_resample_op;
.VAR $tone_resample_op.next = $cbops.NO_MORE_OPERATORS;
.VAR $tone_resample_op.func = &$cbops.mono_upsample_frac;
.VAR $tone_resample_op.param[$cbops.resample.STRUC_SIZE] =
0, // Input index
-1,
1, // Output index
-1,
&$resample.coef_buf,
0,
0.1814058957,
0,
80,
441;
.ENDBLOCK;
// ** allocate memory for stereo audio out cbops copy routine **
.VAR $stereo_out_copy_struc[] =
&$audio_out_dc_remove_op_left, // first operator block
2, // number of inputs
&$audio_out_left_cbuffer_struc, // input
&$audio_out_right_cbuffer_struc, // input
2, // number of outputs
&$audio_out_mix_left_cbuffer_struc, // output
&$audio_out_mix_right_cbuffer_struc; // output
.BLOCK $audio_out_dc_remove_op_left;
.VAR audio_out_dc_remove_op_left.next = &$audio_out_warp_and_shift_op_left;
.VAR audio_out_dc_remove_op_left.func = &$cbops.dc_remove;
.VAR audio_out_dc_remove_op_left.param[$cbops.dc_remove.STRUC_SIZE] =
0, // Input index (left cbuffer)
0; // Output index (left cbuffer)
.ENDBLOCK;
.BLOCK $audio_out_warp_and_shift_op_left;
.VAR audio_out_warp_and_shift_op_left.next = &$audio_out_dc_remove_op_right;
.VAR audio_out_warp_and_shift_op_left.func = &$cbops.warp_and_shift;
.VAR audio_out_warp_and_shift_op_left.param[$cbops.warp_and_shift.STRUC_SIZE] =
0, // Input index (left cbuffer)
2, // Output index (left output port)
-8, // Shift amount
&$WARP_FILTER_COEFS, // warp filter coefs
&audio_out_warp_and_shift_op.left_buf, // warp filter buffer
&$decoder_codec_stream_struc + $codec.stream_decode.WARP_TARGET_FIELD, // warp target address
(WARP_RATE_MAX_RAMP / 1000000 * TMR_PERIOD_AUDIO_COPY); // warp rate max ramp
.ENDBLOCK;
.BLOCK $audio_out_dc_remove_op_right;
.VAR audio_out_dc_remove_op_right.next = &$audio_out_warp_and_shift_op_right;
.VAR audio_out_dc_remove_op_right.func = &$cbops.dc_remove;
.VAR audio_out_dc_remove_op_right.param[$cbops.dc_remove.STRUC_SIZE] =
1, // Input index (right cbuffer)
1; // Output index (right cbuffer)
.ENDBLOCK;
.BLOCK $audio_out_warp_and_shift_op_right;
.VAR audio_out_warp_and_shift_op_right.next = $cbops.NO_MORE_OPERATORS;
.VAR audio_out_warp_and_shift_op_right.func = &$cbops.warp_and_shift;
.VAR audio_out_warp_and_shift_op_right.param[$cbops.warp_and_shift.STRUC_SIZE] =
1, // Input index (right cbuffer)
3, // Output index (right output port)
-8, // Shift amount
&$WARP_FILTER_COEFS, // warp filter coefs
&audio_out_warp_and_shift_op.right_buf, // warp filter buffer
&$decoder_codec_stream_struc + $codec.stream_decode.WARP_TARGET_FIELD, // warp target address
(WARP_RATE_MAX_RAMP / 1000000 * TMR_PERIOD_AUDIO_COPY); // warp rate max ramp
.ENDBLOCK;
// ** Stereo mix output cbops copy routine **
.VAR $stereo_out_mix_copy_struc[] =
&$dac_out_mix_op, // first operator block
2, // number of inputs
&$audio_out_mix_left_cbuffer_struc, // input
&$audio_out_mix_right_cbuffer_struc, // input
2, // number of outputs
$AUDIO_LEFT_OUT_PORT, // output
$AUDIO_RIGHT_OUT_PORT; // output
.BLOCK $dac_out_mix_op;
.VAR dac_out_mix_op.next = &$dac_out_mix_op_left;
.VAR dac_out_mix_op.func = &$cbops.mix;
.VAR dac_out_mix_op.param[] =
&$tone_resample_cbuffer_struc,
0.5, // Mix stream volume
0.5, // Audio stream volume
$cbops.mix.MIXING_STATE_STOPPED, // Mix state - default to not mixing
40, // The number of samples before we start mixing
2, // Number of inputs to mix with
0, // Index of the left input buffer to use
1; // Index of the right input buffer to use
.ENDBLOCK;
.BLOCK $dac_out_mix_op_left;
.VAR $dac_out_mix_op_left.next = &$dac_out_mix_op_right;
.VAR $dac_out_mix_op_left.func = &$cbops.copy_op;
.VAR $dac_out_mix_op_left.param[$cbops.copy_op.STRUC_SIZE] =
0, // Input index
2; // Output index
.ENDBLOCK;
.BLOCK $dac_out_mix_op_right;
.VAR $dac_out_mix_op_right.next = $cbops.NO_MORE_OPERATORS;
.VAR $dac_out_mix_op_right.func = &$cbops.copy_op;
.VAR $dac_out_mix_op_right.param[$cbops.copy_op.STRUC_SIZE] =
1, // Input index
3; // Output index
.ENDBLOCK;
// ** allocate memory for mono audio out cbops copy routine **
.VAR $mono_out_copy_struc[] =
&$audio_out_dc_remove_op_mono, // first operator block
1, // number of inputs
&$audio_out_left_cbuffer_struc, // input
1, // number of outputs
&$audio_out_mix_left_cbuffer_struc;//$AUDIO_LEFT_OUT_PORT; // output
.BLOCK $audio_out_dc_remove_op_mono;
.VAR audio_out_dc_remove_op_mono.next = &$audio_out_warp_and_shift_op_mono;
.VAR audio_out_dc_remove_op_mono.func = &$cbops.dc_remove;
.VAR audio_out_dc_remove_op_mono.param[$cbops.dc_remove.STRUC_SIZE] =
0, // Input index
0; // Output index
.ENDBLOCK;
.BLOCK $audio_out_warp_and_shift_op_mono;
.VAR audio_out_warp_and_shift_op_mono.next = $cbops.NO_MORE_OPERATORS;
.VAR audio_out_warp_and_shift_op_mono.func = &$cbops.warp_and_shift;
.VAR audio_out_warp_and_shift_op_mono.param[$cbops.warp_and_shift.STRUC_SIZE] =
0, // Input index
1, // Output index
-8, // Shift amount
&$WARP_FILTER_COEFS, // warp filter coefs
&audio_out_warp_and_shift_op.left_buf, // warp filter buffer
&$decoder_codec_stream_struc + $codec.stream_decode.WARP_TARGET_FIELD, // warp target address
(WARP_RATE_MAX_RAMP / 1000000 * TMR_PERIOD_AUDIO_COPY); // warp rate max ramp
.ENDBLOCK;
.VAR $mono_out_mix_copy_struc[] =
&$dac_mono_out_mix_op, // first operator block
1, // number of inputs
&$audio_out_mix_left_cbuffer_struc, // input
1, // number of outputs
$AUDIO_LEFT_OUT_PORT; // output
.BLOCK $dac_mono_out_mix_op;
.VAR dac_mono_out_mix_op.next = &$dac_mono_out_op;
.VAR dac_mono_out_mix_op.func = &$cbops.mix;
.VAR dac_mono_out_mix_op.param[] =
&$tone_resample_cbuffer_struc,
0.5, // Mix stream volume
0.5, // Audio stream volume
$cbops.mix.MIXING_STATE_STOPPED, // Mix state - default to not mixing
40, // The number of samples before we start mixing
1, // Number of inputs to mix with
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?