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 + -
显示快捷键?