⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 src.c

📁 au1200 linux2.6.11 硬件解码mae驱动和maiplayer播放器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* <LIC_AMD_STD> * Copyright (C) 2003-2005 Advanced Micro Devices, Inc.  All Rights Reserved. *  * Unless otherwise designated in writing, this software and any related  * documentation are the confidential proprietary information of AMD.  * THESE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY * UNLESS OTHERWISE NOTED IN WRITING, EXPRESS OR IMPLIED WARRANTY OF ANY  * KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,  * NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE AND IN NO  * EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER.  *  * AMD does not assume any responsibility for any errors which may appear  * in the Materials nor any responsibility to support or update the * Materials.  AMD retains the right to modify the Materials at any time,  * without notice, and is not obligated to provide such modified  * Materials to you. AMD is not obligated to furnish, support, or make * any further information available to you. * </LIC_AMD_STD>  *//* <CTL_AMD_STD> * </CTL_AMD_STD>  *//* <DOC_AMD_STD> * Filename: src.c - sampling rate converter * </DOC_AMD_STD>  */#ifdef POSTPROC_SRC#include <stdio.h>#include <string.h>#include "mai_types.h"#include "../audio_out.h" #include "src.h" #if defined(WIN32) || defined(UNDER_CE)  #include <stdlib.h>  #include <io.h>  #else /* Linux */  /* needed under Linux */  #include <unistd.h>  #include <sys/soundcard.h>  #define DEV_AUDIO "/dev/dsp"  static char audio_device[32] = DEV_AUDIO;#endif// #define DAC_MID_RATES_SUPPORTED  /* The I2S DAC supports these rates */#define DAC_MID_RATES_MIGHT_BE_SUPPORTED  /* The I2S DAC supports these rates */// #define DAC_HIGH_RATES_SUPPORTED /* A better DAC will also support these rates */#define USE_CUBIC_SPLINE_FILTER#define DPRINTF(_args_)  /* printf _args_ */#define INFO_PRINTF(_args_) /* printf _args_ */int sampling_rate_conversion_factor;short *conversion_buffer;void close_src(void){  if (sampling_rate_conversion_factor)    free (conversion_buffer);  conversion_buffer = NULL;}/* The assigned values are important, and are used in the calculation of the buffer length. */enum{  CSR_NONE = 0,  CSR_OCTUPLE = 64,  CSR_QUADRUPLE = 32,  CSR_DOUBLE = 16,  CSR_HALVE = 8,  CSR_QUARTER = 4,};#ifdef USE_CUBIC_SPLINE_FILTER#define SPLINE_FIR_LENGTH_MAX 4096typedef struct filter_fir_struct{   int elements;  int output[4];  int *coef;  int *writeptr;  int *readptr;  int *delay_line_end;  int delay_line[SPLINE_FIR_LENGTH_MAX];  int delay_line_length;  int *save;} FILTER_FIR, *PFILTER_FIR;static FILTER_FIR fir[MAX_AUDIO_CHANNELS];#define CS_F_FAC 0x4000int cubic_spline_4x0FIR_coef[4] ={   (int)(-0.0234 * CS_F_FAC),     (int)( 0.2266 * CS_F_FAC),     (int)( 0.8672 * CS_F_FAC),    (int)(-0.0703 * CS_F_FAC),};int /* cs */ cubic_spline_2xFIR_coef[4] = // same as 4x1{  (int)(-0.0625 * CS_F_FAC), /* 1 step in the future */  (int)( 0.5625 * CS_F_FAC), /* time now */  (int)( 0.5625 * CS_F_FAC), /* 1 step in the past */  (int)(-0.0625 * CS_F_FAC), /* 2 steps in the past */};int cubic_spline_4x2FIR_coef[4] ={   (int)(-0.0703 * CS_F_FAC),          (int)( 0.8672 * CS_F_FAC),          (int)( 0.2266 * CS_F_FAC),         (int)(-0.0234 * CS_F_FAC),    };/*  From Matlab script  x = 0:20;  y = [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ] ;   xx = 0:.25:20;  yi = interp1(x,y,xx,'cubic')   -0.0234   -0.0625   -0.0703         0        0.2266    0.5625    0.8672    1.0000        0.8672    0.5625    0.2266         0      -0.0703   -0.0625   -0.0234         0*//*  The cubic-spline filter does a reasonable job with four taps.  It is not as good as an 80-tap fir, but it is a lot less expensive.*/static void upsample_cubic_spline2x(short *input, short *output, int how_many, int channels)  // assumes interleaved streams{  int cc, ii, temp;  int loop = how_many/channels;  int *coef;  int acc;  if ((input == NULL) || (output == NULL) )    return;  for (cc = 0; cc < channels; cc++)       {    fir[cc].elements = 4;    fir[cc].delay_line_end = fir[cc].delay_line + fir[cc].delay_line_length;  }  for (ii = 0; ii < loop; ii++)      // de-interleave and copy to delay lines  {    for (cc = 0; cc < channels; cc++)         {      *fir[cc].writeptr++ = *input++;                  // left is first      if (fir[cc].writeptr >= fir[cc].delay_line_end)  // stay within circular buffer        fir[cc].writeptr -= fir[cc].delay_line_length;    }  }  while (loop--)  {    for (cc = 0; cc < channels; cc++)         {      coef = cubic_spline_2xFIR_coef;      acc = 0x2000;                    // rounding      fir[cc].save = fir[cc].readptr;  // Note that this is the output from the input buffer--NOT the output buffer!      for (ii = 0; ii < fir[cc].elements; ii++) /* do FIR convolution */      {        acc += (*fir[cc].readptr--) * (*coef++);        if (fir[cc].readptr < fir[cc].delay_line)          fir[cc].readptr += fir[cc].delay_line_length;      }      fir[cc].readptr = fir[cc].save;      temp = (int)(acc >> 14);      *output++ = saturate16(temp);           // write to output buffer    }    for (cc = 0; cc < channels; cc++)         {      fir[cc].readptr--;  /* time now is actually 1 step in the past, for a group delay of 1 sample */      if (fir[cc].readptr < fir[cc].delay_line)        fir[cc].readptr += fir[cc].delay_line_length;      // Now output the next unmodified sample for a 2x upsample      *output++ = (short)*fir[cc].readptr;      fir[cc].readptr += 2;      if (fir[cc].readptr >= fir[cc].delay_line_end)        fir[cc].readptr -= fir[cc].delay_line_length;    }  }}static void upsample_cubic_spline4x(short *input, short *output, int how_many, int channels)  // assumes interleaved streams{  int cc, ii, temp;  int loop = how_many/channels;  int *coef;  int acc;  if ((input == NULL) || (output == NULL) )    return;  for (cc = 0; cc < channels; cc++)       {    fir[cc].elements = 4;    fir[cc].delay_line_end = fir[cc].delay_line + fir[cc].delay_line_length;  }  for (ii = 0; ii < loop; ii++)      // de-interleave and copy to delay lines  {    for (cc = 0; cc < channels; cc++)         {      *fir[cc].writeptr++ = *input++;                  // left is first      if (fir[cc].writeptr >= fir[cc].delay_line_end)  // stay within circular buffer        fir[cc].writeptr -= fir[cc].delay_line_length;    }  }  while (loop--)  {    for (cc = 0; cc < channels; cc++)         {      coef = cubic_spline_4x0FIR_coef;      acc = 0x2000;                    // rounding      fir[cc].save = fir[cc].readptr;  // Note that this is from the input buffer--NOT the output buffer!      for (ii = 0; ii < fir[cc].elements; ii++) /* do FIR convolution using 4 values */      {        acc += (*fir[cc].readptr--) * (*coef++);        if (fir[cc].readptr < fir[cc].delay_line)          fir[cc].readptr += fir[cc].delay_line_length;      }      fir[cc].readptr = fir[cc].save;      temp = (int)(acc >> 14);      fir[cc].output[0] = saturate16(temp);       coef = cubic_spline_2xFIR_coef;  // same as 4x1FIR_coef would be      acc = 0x2000;                    // rounding      for (ii = 0; ii < fir[cc].elements; ii++) /* do FIR convolution using 4 values */      {        acc += (*fir[cc].readptr--) * (*coef++);        if (fir[cc].readptr < fir[cc].delay_line)          fir[cc].readptr += fir[cc].delay_line_length;      }      fir[cc].readptr = fir[cc].save;      temp = (int)(acc >> 14);      fir[cc].output[1] = saturate16(temp);       coef = cubic_spline_4x2FIR_coef;       acc = 0x2000;                    // rounding      for (ii = 0; ii < fir[cc].elements; ii++) /* do FIR convolution using 4 values */      {        acc += (*fir[cc].readptr--) * (*coef++);        if (fir[cc].readptr < fir[cc].delay_line)          fir[cc].readptr += fir[cc].delay_line_length;      }      temp = (int)(acc >> 14);      fir[cc].output[2] = saturate16(temp);       fir[cc].readptr = fir[cc].save-1;      /* time now is actually 1 step in the past, for a group delay of 1 sample */      if (fir[cc].readptr < fir[cc].delay_line)        fir[cc].readptr += fir[cc].delay_line_length;      // Now use the next unmodified sample for 4x3 upsample      fir[cc].output[3] = *fir[cc].readptr;      fir[cc].readptr += 2; /* move to the next input sample */      if (fir[cc].readptr >= fir[cc].delay_line_end)        fir[cc].readptr -= fir[cc].delay_line_length;    }    /* interleave results */    for (ii = 0; ii < fir[0].elements; ii++)           for (cc = 0; cc < channels; cc++)             *output++ = fir[cc].output[ii];  }}#endif/* This is, for now, the classic add/drop-sample method without filtering, except where cubic spline is used. */static int csr_leftover;static short csr_leftoverbuf[32];static short *csr_buf;static short *csr_buf_base;short *convert_sampling_rate(short *inbuf, int *length /* in bytes */) // assumes 16 bits per sample {  int ii, jj;  int loop;  short *buf = inbuf;  if ((inbuf == NULL) || (*length == 0))    return NULL;  /* only do this if we are downsampling */  if ((sampling_rate_conversion_factor == CSR_HALVE) || (sampling_rate_conversion_factor == CSR_QUARTER))  {    if (csr_buf_base == NULL)      csr_buf_base = (short *)malloc(16384);    if (csr_buf_base != NULL)    {      if (csr_leftover)      {        csr_buf = csr_buf_base;        memcpy(csr_buf, csr_leftoverbuf, csr_leftover);        memcpy(((unsigned char*)csr_buf) + csr_leftover, buf, *length);        *length += csr_leftover;        csr_leftover = 0;        buf = csr_buf;      }      if (*length & 0xf)  // odd lengths are a problem when downsampling      {        int slength = *length & 0xfffff0;         csr_leftover = *length - slength;        memcpy(csr_leftoverbuf, ((unsigned char*)buf) + slength, csr_leftover);        *length = slength;      }    }  }  else if (csr_buf_base != NULL)  {    free(csr_buf_base);    csr_buf_base = NULL;  }  loop = *length / sizeof(short);  if (number_of_channels == 1)  {    switch (sampling_rate_conversion_factor)    {      case CSR_OCTUPLE: // FIXIT use a cubic spline for this one too        for (jj = 0, ii = 0; ii < loop; ii++, jj += 8)        {          conversion_buffer[jj] = buf[ii];          conversion_buffer[jj+1] = buf[ii];          conversion_buffer[jj+2] = buf[ii];          conversion_buffer[jj+3] = buf[ii];          conversion_buffer[jj+4] = buf[ii];          conversion_buffer[jj+5] = buf[ii];          conversion_buffer[jj+6] = buf[ii];          conversion_buffer[jj+7] = buf[ii];        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -