![]() |
Mixxx
|
00001 // sampleutil.h 00002 // Created 10/5/2009 by RJ Ryan (rryan@mit.edu) 00003 00004 #ifndef SAMPLEUTIL_H 00005 #define SAMPLEUTIL_H 00006 00007 #include "defs.h" 00008 00009 // MSVC does this 00010 // __declspec(align(16)) 00011 // while GCC does 00012 // __attribute__((aligned(16))) 00013 // IntelCC does 00014 // _MM_ALIGN_16 00015 // but I dont know how to test for ICC. 00016 00017 #if !_ALIGN_16 00018 #define _ALIGN_16 00019 #define _ALIGN_STACK 00020 #elif (defined __GNUC__) 00021 #define _ALIGN_16 __attribute__((aligned(16))) 00022 #define _ALIGN_STACK __attribute__((force_align_arg_pointer, aligned(16))) 00023 #elif (defined _MSC_VER) 00024 #define _ALIGN_16 __declspec(align(16)) 00025 #define _ALIGN_STACK 00026 #else 00027 #error Please email mixxx-devel@lists.sourceforge.net and tell us what is the equivalent of __attribute__((aligned(16))) for your compiler. 00028 #endif 00029 00030 #define assert_aligned(data) (Q_ASSERT(reinterpret_cast<int64_t>(data) % 16 == 0)); 00031 00032 // A group of utilities for working with samples. Automatically use SSE/SSE2 00033 // optimizations where possible. 00034 class SampleUtil { 00035 public: 00036 00037 // Allocated a buffer of CSAMPLE's with length size. Ensures that the buffer 00038 // is 16-byte aligned for use for use with SampleUtil SSE enhanced 00039 // functions. 00040 static CSAMPLE* alloc(int size); 00041 00042 // Frees a 16-byte aligned buffer allocated by SampleUtil::alloc() 00043 static void free(CSAMPLE* pBuffer); 00044 00045 // Multiply every sample in pBuffer by gain 00046 static void applyGain(CSAMPLE* pBuffer, CSAMPLE gain, int iNumSamples); 00047 00048 // Apply a different gain to every other sample. 00049 static void applyAlternatingGain(CSAMPLE* pBuffer, 00050 CSAMPLE gain1, CSAMPLE gain2, 00051 int iNumSamples); 00052 00053 // Add each sample of pSrc, multiplied by the gain, to pDest 00054 static void addWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, 00055 CSAMPLE gain, int iNumSamples); 00056 00057 // Add to each sample of pDest, pSrc1 multiplied by gain1 plus pSrc2 00058 // multiplied by gain2 00059 static void add2WithGain(CSAMPLE* pDest, 00060 const CSAMPLE* pSrc1, CSAMPLE gain1, 00061 const CSAMPLE* pSrc2, CSAMPLE gain2, 00062 int iNumSamples); 00063 00064 // Add to each sample of pDest, pSrc1 multiplied by gain1 plus pSrc2 00065 // multiplied by gain2 plus pSrc3 multiplied by gain3 00066 static void add3WithGain(CSAMPLE* pDest, 00067 const CSAMPLE* pSrc1, CSAMPLE gain1, 00068 const CSAMPLE* pSrc2, CSAMPLE gain2, 00069 const CSAMPLE* pSrc3, CSAMPLE gain3, 00070 int iNumSamples); 00071 00072 // Copy pSrc to pDest and multiply each sample by a factor of gain. 00073 static void copyWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, 00074 CSAMPLE gain, int iNumSamples); 00075 00076 // Copies the sum of each channel, multiplied by its gain into pDest 00077 static void copy2WithGain(CSAMPLE* pDest, 00078 const CSAMPLE* pSrc1, CSAMPLE gain1, 00079 const CSAMPLE* pSrc2, CSAMPLE gain2, 00080 int iNumSamples); 00081 00082 // Copies the sum of each channel, multiplied by its gain into pDest 00083 static void copy3WithGain(CSAMPLE* pDest, 00084 const CSAMPLE* pSrc1, CSAMPLE gain1, 00085 const CSAMPLE* pSrc2, CSAMPLE gain2, 00086 const CSAMPLE* pSrc3, CSAMPLE gain3, 00087 int iNumSamples); 00088 00089 // Copies the sum of each channel, multiplied by its gain into pDest 00090 static void copy4WithGain(CSAMPLE* pDest, 00091 const CSAMPLE* pSrc1, CSAMPLE gain1, 00092 const CSAMPLE* pSrc2, CSAMPLE gain2, 00093 const CSAMPLE* pSrc3, CSAMPLE gain3, 00094 const CSAMPLE* pSrc4, CSAMPLE gain4, 00095 int iNumSamples); 00096 00097 // Copies the sum of each channel, multiplied by its gain into pDest 00098 static void copy5WithGain(CSAMPLE* pDest, 00099 const CSAMPLE* pSrc1, CSAMPLE gain1, 00100 const CSAMPLE* pSrc2, CSAMPLE gain2, 00101 const CSAMPLE* pSrc3, CSAMPLE gain3, 00102 const CSAMPLE* pSrc4, CSAMPLE gain4, 00103 const CSAMPLE* pSrc5, CSAMPLE gain5, 00104 int iNumSamples); 00105 00106 // Copies the sum of each channel, multiplied by its gain into pDest 00107 static void copy6WithGain(CSAMPLE* pDest, 00108 const CSAMPLE* pSrc1, CSAMPLE gain1, 00109 const CSAMPLE* pSrc2, CSAMPLE gain2, 00110 const CSAMPLE* pSrc3, CSAMPLE gain3, 00111 const CSAMPLE* pSrc4, CSAMPLE gain4, 00112 const CSAMPLE* pSrc5, CSAMPLE gain5, 00113 const CSAMPLE* pSrc6, CSAMPLE gain6, 00114 int iNumSamples); 00115 00116 // Copies the sum of each channel, multiplied by its gain into pDest 00117 static void copy7WithGain(CSAMPLE* pDest, 00118 const CSAMPLE* pSrc1, CSAMPLE gain1, 00119 const CSAMPLE* pSrc2, CSAMPLE gain2, 00120 const CSAMPLE* pSrc3, CSAMPLE gain3, 00121 const CSAMPLE* pSrc4, CSAMPLE gain4, 00122 const CSAMPLE* pSrc5, CSAMPLE gain5, 00123 const CSAMPLE* pSrc6, CSAMPLE gain6, 00124 const CSAMPLE* pSrc7, CSAMPLE gain7, 00125 int iNumSamples); 00126 00127 // Convert a buffer of SAMPLEs to a buffer of CSAMPLEs. Does not work 00128 // in-place! pDest and pSrc must not be aliased. 00129 static void convert(CSAMPLE* pDest, const SAMPLE* pSrc, int iNumSamples); 00130 00131 // For each pair of samples in pBuffer (l,r) -- stores the sum of the 00132 // absolute values of l in pfAbsL, and the sum of the absolute values of r 00133 // in pfAbsR. 00134 static void sumAbsPerChannel(CSAMPLE* pfAbsL, CSAMPLE* pfAbsR, 00135 const CSAMPLE* pBuffer, int iNumSamples); 00136 00137 // Returns true if the buffer contains any samples outside of the range 00138 // [fMin,fMax]. 00139 static bool isOutsideRange(CSAMPLE fMax, CSAMPLE fMin, 00140 const CSAMPLE* pBuffer, int iNumSamples); 00141 00142 // Copied every sample in pSrc to pDest, limiting the values in pDest to the 00143 // range [fMin, fMax]. If pDest and pSrc are aliases, will not copy -- will 00144 // only clamp. Returns true if any samples in pSrc were outside the range 00145 // [fMin, fMax]. 00146 static bool copyClampBuffer(CSAMPLE fMax, CSAMPLE fMin, 00147 CSAMPLE* pDest, const CSAMPLE* pSrc, 00148 int iNumSamples); 00149 00150 // Interleave the samples in pSrc1 and pSrc2 into pDest. iNumSamples must be 00151 // the number of samples in pSrc1 and pSrc2, and pDest must have at least 00152 // space for iNumSamples*2 samples. pDest must not be an alias of pSrc1 or 00153 // pSrc2. 00154 static void interleaveBuffer(CSAMPLE* pDest, 00155 const CSAMPLE* pSrc1, const CSAMPLE* pSrc2, 00156 int iNumSamples); 00157 00158 // Deinterleave the samples in pSrc alternately into pDest1 and 00159 // pDest2. iNumSamples must be the number of samples in pDest1 and pDest2, 00160 // and pSrc must have at least iNumSamples*2 samples. Neither pDest1 or 00161 // pDest2 can be aliases of pSrc. 00162 static void deinterleaveBuffer(CSAMPLE* pDest1, CSAMPLE* pDest2, 00163 const CSAMPLE* pSrc, int iNumSamples); 00164 00165 static void setOptimizations(bool opt); 00166 00167 private: 00168 static bool m_sOptimizationsOn; 00169 static void sseApplyGain(CSAMPLE* pBuffer, 00170 CSAMPLE gain, int iNumSamples) _ALIGN_STACK; 00171 static void sseApplyAlternatingGain(CSAMPLE* pBuffer, 00172 CSAMPLE gain1, CSAMPLE gain2, 00173 int iNumSamples) _ALIGN_STACK; 00174 static void sseAddWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, 00175 CSAMPLE gain, int iNumSamples) _ALIGN_STACK; 00176 static void sseAdd2WithGain(CSAMPLE* pDest, 00177 const CSAMPLE* pSrc1, CSAMPLE gain1, 00178 const CSAMPLE* pSrc2, CSAMPLE gain2, 00179 int iNumSamples) _ALIGN_STACK; 00180 static void sseAdd3WithGain(CSAMPLE* pDest, 00181 const CSAMPLE* pSrc1, CSAMPLE gain1, 00182 const CSAMPLE* pSrc2, CSAMPLE gain2, 00183 const CSAMPLE* pSrc3, CSAMPLE gain3, 00184 int iNumSamples) _ALIGN_STACK; 00185 00186 static void sseCopyWithGain(CSAMPLE* pDest, const CSAMPLE* pSrc, 00187 CSAMPLE gain, int iNumSamples) _ALIGN_STACK; 00188 static void sseCopy2WithGain(CSAMPLE* pDest, 00189 const CSAMPLE* pSrc1, CSAMPLE gain1, 00190 const CSAMPLE* pSrc2, CSAMPLE gain2, 00191 int iNumSamples) _ALIGN_STACK; 00192 static void sseCopy3WithGain(CSAMPLE* pDest, 00193 const CSAMPLE* pSrc1, CSAMPLE gain1, 00194 const CSAMPLE* pSrc2, CSAMPLE gain2, 00195 const CSAMPLE* pSrc3, CSAMPLE gain3, 00196 int iNumSamples) _ALIGN_STACK; 00197 static void sseConvert(CSAMPLE* pDest, 00198 const SAMPLE* pSrc, int iNumSamples) _ALIGN_STACK; 00199 static void sseSumAbsPerChannel(CSAMPLE* pfAbsL, CSAMPLE* pfAbsR, 00200 const CSAMPLE* pBuffer, 00201 int iNumSamples) _ALIGN_STACK; 00202 static bool sseIsOutsideRange(CSAMPLE fMax, CSAMPLE fMin, 00203 const CSAMPLE* pBuffer, 00204 int iNumSamples) _ALIGN_STACK; 00205 static bool sseCopyClampBuffer(CSAMPLE fMax, CSAMPLE fMin, 00206 CSAMPLE* pDest, const CSAMPLE* pSrc, 00207 int iNumSamples) _ALIGN_STACK; 00208 static void sseInterleaveBuffer(CSAMPLE* pDest, 00209 const CSAMPLE* pSrc1, const CSAMPLE* pSrc2, 00210 int iNumSamples) _ALIGN_STACK; 00211 static void sseDeinterleaveBuffer(CSAMPLE* pDest1, CSAMPLE* pDest2, 00212 const CSAMPLE* pSrc, 00213 int iNumSamples) _ALIGN_STACK; 00214 00215 00216 00217 }; 00218 00219 00220 #endif /* SAMPLEUTIL_H */