📄 aflibconverter.cc
字号:
/* * Copyright: (C) 2000 Julius O. Smith * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Julius O. Smith jos@ccrma.stanford.edu * *//* This code was modified by Bruce Forsberg (forsberg@tns.net) to make it into a C++ class*/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include "aflibConverter.h"#include "aflibConverterLargeFilter.h"#include "aflibConverterSmallFilter.h"#include "aflibDebug.h"#if (!defined(TRUE) || !defined(FALSE))# define TRUE 1# define FALSE 0#endif /* * The configuration constants below govern * the number of bits in the input sample and filter coefficients, the * number of bits to the right of the binary-point for fixed-point math, etc. *//* Conversion constants */#define Nhc 8#define Na 7#define Np (Nhc+Na)#define Npc (1<<Nhc)#define Amask ((1<<Na)-1)#define Pmask ((1<<Np)-1)#define Nh 16#define Nb 16#define Nhxn 14#define Nhg (Nh-Nhxn)#define NLpScl 13/* Description of constants: * * Npc - is the number of look-up values available for the lowpass filter * between the beginning of its impulse response and the "cutoff time" * of the filter. The cutoff time is defined as the reciprocal of the * lowpass-filter cut off frequence in Hz. For example, if the * lowpass filter were a sinc function, Npc would be the index of the * impulse-response lookup-table corresponding to the first zero- * crossing of the sinc function. (The inverse first zero-crossing * time of a sinc function equals its nominal cutoff frequency in Hz.) * Npc must be a power of 2 due to the details of the current * implementation. The default value of 512 is sufficiently high that * using linear interpolation to fill in between the table entries * gives approximately 16-bit accuracy in filter coefficients. * * Nhc - is log base 2 of Npc. * * Na - is the number of bits devoted to linear interpolation of the * filter coefficients. * * Np - is Na + Nhc, the number of bits to the right of the binary point * in the integer "time" variable. To the left of the point, it indexes * the input array (X), and to the right, it is interpreted as a number * between 0 and 1 sample of the input X. Np must be less than 16 in * this implementation. * * Nh - is the number of bits in the filter coefficients. The sum of Nh and * the number of bits in the input data (typically 16) cannot exceed 32. * Thus Nh should be 16. The largest filter coefficient should nearly * fill 16 bits (32767). * * Nb - is the number of bits in the input data. The sum of Nb and Nh cannot * exceed 32. * * Nhxn - is the number of bits to right shift after multiplying each input * sample times a filter coefficient. It can be as great as Nh and as * small as 0. Nhxn = Nh-2 gives 2 guard bits in the multiply-add * accumulation. If Nhxn=0, the accumulation will soon overflow 32 bits. * * Nhg - is the number of guard bits in mpy-add accumulation (equal to Nh-Nhxn) * * NLpScl - is the number of bits allocated to the unity-gain normalization * factor. The output of the lowpass filter is multiplied by LpScl and * then right-shifted NLpScl bits. To avoid overflow, we must have * Nb+Nhg+NLpScl < 32. */aflibConverter::aflibConverter( bool high_quality, bool linear_interpolation, bool filter_interpolation){ /* TODO put all these into an enum as it only makes sense to have * one true at a time. - DAS */ interpFilt = filter_interpolation; largeFilter = high_quality; linearInterp = linear_interpolation; _X = NULL; _Y = NULL; _vol = 1.0;}aflibConverter::~aflibConverter(){ deleteMemory();}voidaflibConverter::deleteMemory(){ int i; // Delete memory for the input and output arrays if (_X != NULL) { for (i = 0; i < _nChans; i++) { delete [] _X[i]; _X[i] = NULL; delete [] _Y[i]; _Y[i] = NULL; } delete [] _X; _X = NULL; delete [] _Y; _Y = NULL; }}voidaflibConverter::initialize( double fac, int channels, double volume){// This function will allow one to stream data. When a new data stream is to// be input then this function should be called. Even if the factor and number// of channels don't change. Otherwise each new data block sent to resample// will be considered part of the previous data block. This function also allows// one to specified a multiplication factor to adjust the final output. This// applies to the small and large filter. int i; // Delete all previous allocated input and output buffer memory deleteMemory(); _factor = fac; _nChans = channels; _initial = TRUE; _vol = volume; // Allocate all new memory _X = new short * [_nChans]; _Y = new short * [_nChans]; for (i = 0; i < _nChans; i++) { // Add extra to allow of offset of input data (Xoff in main routine) _X[i] = new short[IBUFFSIZE + 256]; _Y[i] = new short[(int)(((double)IBUFFSIZE)*_factor)]; memset(_X[i], 0, sizeof(short) * (IBUFFSIZE + 256)); }}intaflibConverter::resample( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ short inArray[], /* input data */ short outArray[]) /* output data */{ int Ycount; // Use fast method with no filtering. Poor quality if (linearInterp == TRUE) Ycount = resampleFast(inCount,outCount,inArray,outArray); // Use small filtering. Good qulaity else if (largeFilter == FALSE) Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, SMALL_FILTER_IMP, SMALL_FILTER_IMPD, (unsigned short)(SMALL_FILTER_SCALE * _vol), SMALL_FILTER_NMULT, SMALL_FILTER_NWING); // Use large filtering Great quality else Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, LARGE_FILTER_IMP, LARGE_FILTER_IMPD, (unsigned short)(LARGE_FILTER_SCALE * _vol), LARGE_FILTER_NMULT, LARGE_FILTER_NWING); _initial = FALSE; return (Ycount);}intaflibConverter::err_ret(char *s){ aflib_debug("resample: %s \n\n",s); /* Display error message */ return -1;}intaflibConverter::readData( int inCount, /* _total_ number of frames in input file */ short inArray[], /* input data */ short *outPtr[], /* array receiving chan samps */ int dataArraySize, /* size of these arrays */ int Xoff, /* read into input array starting at this index */ bool init_count) { int i, Nsamps, c; static unsigned int framecount; /* frames previously read */ short *ptr; if (init_count == TRUE) framecount = 0; /* init this too */ Nsamps = dataArraySize - Xoff; /* Calculate number of samples to get */ // Don't overrun input buffers if (Nsamps > (inCount - (int)framecount)) { Nsamps = inCount - framecount; } for (c = 0; c < _nChans; c++) { ptr = outPtr[c]; ptr += Xoff; /* Start at designated sample number */ for (i = 0; i < Nsamps; i++) *ptr++ = (short) inArray[c * inCount + i + framecount]; } framecount += Nsamps; if ((int)framecount >= inCount) /* return index of last samp */ return (((Nsamps - (framecount - inCount)) - 1) + Xoff); else return 0;}intaflibConverter::SrcLinear( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout){ short iconst; short *Xp, *Ystart; int v,x1,x2; double dt; /* Step through input signal */ unsigned int dtb; /* Fixed-point version of Dt */// unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int start_sample, end_sample; dt = 1.0/factor; /* Output sampling period */ dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */ start_sample = (*Time)>>Np; Ystart = Y;// endTime = *Time + (1<<Np)*(int)Nx; /* * TODO * DAS: not sure why this was changed from *Time < endTime * update: *Time < endTime causes seg fault. Also adds a clicking sound. */ while (Y - Ystart != Nout)// while (*Time < endTime) { iconst = (*Time) & Pmask; Xp = &X[(*Time)>>Np]; /* Ptr to current input sample */ x1 = *Xp++; x2 = *Xp; x1 *= ((1<<Np)-iconst); x2 *= iconst; v = x1 + x2; *Y++ = WordToHword(v,Np); /* Deposit output */ *Time += dtb; /* Move to next sample by time increment */ } end_sample = (*Time)>>Np; Nx = end_sample - start_sample; return (Y - Ystart); /* Return number of output samples */}intaflibConverter::SrcUp( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout, unsigned short Nwing, unsigned short LpScl, short Imp[], short ImpD[], bool Interp){ short *Xp, *Ystart; int v; double dt; /* Step through input signal */ unsigned int dtb; /* Fixed-point version of Dt */// unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int start_sample, end_sample; dt = 1.0/factor; /* Output sampling period */ dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */ start_sample = (*Time)>>Np; Ystart = Y;// endTime = *Time + (1<<Np)*(int)Nx; /* * TODO * DAS: not sure why this was changed from *Time < endTime * update: *Time < endTime causes seg fault. Also adds a clicking sound. */ while (Y - Ystart != Nout)// while (*Time < endTime) { Xp = &X[*Time>>Np]; /* Ptr to current input sample */ /* Perform left-wing inner product */ v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask),-1); /* Perform right-wing inner product */ v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, (short)((((*Time)^Pmask)+1)&Pmask), 1); v >>= Nhg; /* Make guard bits */ v *= LpScl; /* Normalize for unity filter gain */ *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ *Time += dtb; /* Move to next sample by time increment */ } end_sample = (*Time)>>Np; Nx = end_sample - start_sample; return (Y - Ystart); /* Return the number of output samples */}intaflibConverter::SrcUD( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout, unsigned short Nwing, unsigned short LpScl, short Imp[], short ImpD[], bool Interp){ short *Xp, *Ystart; int v; double dh; /* Step through filter impulse response */ double dt; /* Step through input signal */// unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int dhb, dtb; /* Fixed-point versions of Dh,Dt */ unsigned int start_sample, end_sample;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -