00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "stdafx.h"
00025 #include "Audio.h"
00026
00027 static long audio_pointsample_8(void *dst, void *src, long accum, long samp_frac, long cnt) {
00028 unsigned char *d = (unsigned char *)dst;
00029 unsigned char *s = (unsigned char *)src;
00030
00031 do {
00032 *d++ = s[accum>>19];
00033 accum += samp_frac;
00034 } while(--cnt);
00035
00036 return accum;
00037 }
00038
00039 static long audio_pointsample_16(void *dst, void *src, long accum, long samp_frac, long cnt) {
00040 unsigned short *d = (unsigned short *)dst;
00041 unsigned short *s = (unsigned short *)src;
00042
00043 do {
00044 *d++ = s[accum>>19];
00045 accum += samp_frac;
00046 } while(--cnt);
00047
00048 return accum;
00049 }
00050
00051 static long audio_pointsample_32(void *dst, void *src, long accum, long samp_frac, long cnt) {
00052 unsigned long *d = (unsigned long *)dst;
00053 unsigned long *s = (unsigned long *)src;
00054
00055 do {
00056 *d++ = s[accum>>19];
00057 accum += samp_frac;
00058 } while(--cnt);
00059
00060 return accum;
00061 }
00062
00063 static long audio_downsample_mono8(void *dst, void *src, long *filter_bank, int filter_width, long accum, long samp_frac, long cnt) {
00064 unsigned char *d = (unsigned char *)dst;
00065 unsigned char *s = (unsigned char *)src;
00066
00067 do {
00068 long sum = 0;
00069 int w;
00070 long *fb_ptr;
00071 unsigned char *s_ptr;
00072
00073 w = filter_width;
00074 fb_ptr = filter_bank + filter_width * ((accum>>11)&0xff);
00075 s_ptr = s + (accum>>19);
00076 do {
00077 sum += *fb_ptr++ * (int)*s_ptr++;
00078 } while(--w);
00079
00080 if (sum < 0)
00081 *d++ = 0;
00082 else if (sum > 0x3fffff)
00083 *d++ = 0xff;
00084 else
00085 *d++ = ((sum + 0x2000)>>14);
00086
00087 accum += samp_frac;
00088 } while(--cnt);
00089
00090 return accum;
00091 }
00092
00093 static long audio_downsample_mono16(void *dst, void *src, long *filter_bank, int filter_width, long accum, long samp_frac, long cnt) {
00094 signed short *d = (signed short *)dst;
00095 signed short *s = (signed short *)src;
00096
00097 do {
00098 long sum = 0;
00099 int w;
00100 long *fb_ptr;
00101 signed short *s_ptr;
00102
00103 w = filter_width;
00104 fb_ptr = filter_bank + filter_width * ((accum>>11)&0xff);
00105 s_ptr = s + (accum>>19);
00106 do {
00107 sum += *fb_ptr++ * (int)*s_ptr++;
00108 } while(--w);
00109
00110 if (sum < -0x20000000)
00111 *d++ = -0x8000;
00112 else if (sum > 0x1fffffff)
00113 *d++ = 0x7fff;
00114 else
00115 *d++ = ((sum + 0x2000)>>14);
00116
00117 accum += samp_frac;
00118 } while(--cnt);
00119
00120 return accum;
00121 }
00122
00123
00124 static int permute_index(int a, int b) {
00125 return (b-(a>>8)-1) + (a&255)*b;
00126 }
00127
00128 static void make_downsample_filter(long *filter_bank, int filter_width, long samp_frac) {
00129 int i, j, v;
00130 double filt_max;
00131 double filtwidth_frac;
00132
00133 filtwidth_frac = samp_frac/2048.0;
00134
00135 filter_bank[filter_width-1] = 0;
00136
00137 filt_max = (16384.0 * 524288.0) / samp_frac;
00138
00139 for(i=0; i<128*filter_width; i++) {
00140 int y = 0;
00141 double d = i / filtwidth_frac;
00142
00143 if (d<1.0)
00144 y = (int)(0.5 + filt_max*(1.0 - d));
00145
00146 filter_bank[permute_index(128*filter_width + i, filter_width)]
00147 = filter_bank[permute_index(128*filter_width - i, filter_width)]
00148 = y;
00149 }
00150
00151
00152
00153 for(i=0; i<256*filter_width; i+=filter_width) {
00154 v=0;
00155 for(j=0; j<filter_width; j++)
00156 v += filter_bank[i+j];
00157
00158
00159
00160 v = (0x4000 - v)/filter_width;
00161 for(j=0; j<filter_width; j++)
00162 filter_bank[i+j] += v;
00163 }
00164
00165
00166 }
00167
00168 AudioStreamResampler::AudioStreamResampler(int bps, long org_rate, long new_rate, bool fHighQuality)
00169 {
00170 samp_frac = 0x80000;
00171
00172 this->bps = bps;
00173
00174 if(bps == 1)
00175 {
00176 ptsampleRout = audio_pointsample_8;
00177 dnsampleRout = audio_downsample_mono8;
00178 }
00179 else if(bps >= 2)
00180 {
00181 ptsampleRout = audio_pointsample_16;
00182 dnsampleRout = audio_downsample_mono16;
00183 }
00184 else
00185 {
00186 return;
00187 }
00188
00189
00190 samp_frac = MulDiv(org_rate, 0x80000, new_rate);
00191
00192 holdover = 0;
00193 filter_bank = NULL;
00194 filter_width = 1;
00195 accum = 0;
00196
00197
00198
00199 if(fHighQuality)
00200 {
00201 if(samp_frac>0x80000)
00202 {
00203
00204
00205 filter_width = ((samp_frac + 0x7ffff)>>19)<<1 <<1;
00206
00207 if(!(filter_bank = new long[filter_width * 256]))
00208 {
00209 filter_width = 1;
00210 return;
00211 }
00212
00213 make_downsample_filter(filter_bank, filter_width, samp_frac);
00214
00215
00216
00217 memset(cbuffer, bps >= 2 ? 0 : 0x80, bps*filter_width);
00218
00219 holdover = filter_width/2;
00220 }
00221 }
00222 }
00223
00224 AudioStreamResampler::~AudioStreamResampler()
00225 {
00226 delete [] filter_bank;
00227 }
00228
00229 long AudioStreamResampler::Downsample(void* input, long samplesin, void* output, long samplesout)
00230 {
00231 long lActualSamples = 0;
00232
00233
00234
00235
00236
00237
00238 while(samplesin > 0 && samplesout > 0)
00239 {
00240 long srcSamples, dstSamples;
00241 int nhold;
00242
00243
00244
00245
00246
00247
00248
00249 srcSamples = (long)(((__int64)samp_frac*(samplesout-1) + accum) >> 19) + filter_width - holdover;
00250
00251
00252
00253 if(srcSamples > BUFFER_SIZE - holdover)
00254 srcSamples = BUFFER_SIZE - holdover;
00255
00256
00257
00258 srcSamples = min(srcSamples, samplesin);
00259 if(!srcSamples) break;
00260
00261 memcpy((char*)cbuffer + holdover*bps, (char*)input, srcSamples*bps);
00262 input = (void *)((char *)input + srcSamples*bps);
00263
00264
00265
00266
00267
00268
00269 dstSamples = (((__int64)(srcSamples+holdover-filter_width)<<19) + 0x7ffff - accum) / samp_frac + 1;
00270
00271 if(dstSamples > samplesout)
00272 dstSamples = samplesout;
00273
00274 if(dstSamples >= 1)
00275 {
00276 if(filter_bank)
00277 accum = dnsampleRout(output, cbuffer, filter_bank, filter_width, accum, samp_frac, dstSamples);
00278 else
00279 accum = ptsampleRout(output, cbuffer, accum, samp_frac, dstSamples);
00280
00281 output = (void *)((char *)output + bps * dstSamples);
00282 lActualSamples += dstSamples;
00283 samplesout -= dstSamples;
00284 }
00285
00286
00287
00288
00289
00290 accum -= ((srcSamples+holdover)<<19);
00291
00292
00293
00294
00295
00296
00297 nhold = - (accum>>19);
00298
00299
00300
00301 if (nhold>0) {
00302 memmove(cbuffer, (char *)cbuffer+bps*(srcSamples+holdover-nhold), bps*nhold);
00303 holdover = nhold;
00304 accum += nhold<<19;
00305 } else
00306 holdover = 0;
00307
00308
00309 }
00310
00311 int Bytes = lActualSamples * bps;
00312
00313 return lActualSamples;
00314 }