desc:Upsamp Test @init upsampfact=8; filtlen = 25; datasize=100; filtb=0; // size filtlen input=filtb+filtlen; // size datasize output=input+datasize; // size datasize*upsampfact work=output+datasize*upsampfact; // size datasize*upsampfact // create the original waveform in the input buffer: didx=0; loop(datasize, input[didx]=sin(2*2*$pi*didx/datasize)+sin(20.3834724*2*$pi*didx/datasize); didx+=1; ); // srate 44100 upsampled 8X 25-order 0.5442176870748299-Hz, 0.1360544217687075-Hz-width linear phase FIR lowpass // e.g. at 44.1k that's a 12kHz cutoff with 3kHz transition filtb[0] = 0.0125287023096614606038068373550231626722961664199829101562500000000000000000000000000000000000000000; filtb[1] = 0.0178100495406813379151156340185480075888335704803466796875000000000000000000000000000000000000000000; filtb[2] = 0.0232562730997107544594904027235315879806876182556152343750000000000000000000000000000000000000000000; filtb[3] = 0.0287370345711178490355486303542420500889420509338378906250000000000000000000000000000000000000000000; filtb[4] = 0.0341170092244123396296728856214031111449003219604492187500000000000000000000000000000000000000000000; filtb[5] = 0.0392600347372514466015580580915411701425909996032714843750000000000000000000000000000000000000000000; filtb[6] = 0.0440333482528297986968723876088915858417749404907226562500000000000000000000000000000000000000000000; filtb[7] = 0.0483117659859851472647918058100913185626268386840820312500000000000000000000000000000000000000000000; filtb[8] = 0.0519816604677718271942943317753815790638327598571777343750000000000000000000000000000000000000000000; filtb[9] = 0.0549445967117400263513005143067857716232538223266601562500000000000000000000000000000000000000000000; filtb[10] = 0.0571204998906782099310497358146676560863852500915527343750000000000000000000000000000000000000000000; filtb[11] = 0.0584502431287390947223236992158490465953946113586425781250000000000000000000000000000000000000000000; filtb[12] = 0.0588975641588412590632373166954494081437587738037109375000000000000000000000000000000000000000000000; filtb[13] = 0.0584502431287390947223236992158490465953946113586425781250000000000000000000000000000000000000000000; filtb[14] = 0.0571204998906782099310497358146676560863852500915527343750000000000000000000000000000000000000000000; filtb[15] = 0.0549445967117400263513005143067857716232538223266601562500000000000000000000000000000000000000000000; filtb[16] = 0.0519816604677718271942943317753815790638327598571777343750000000000000000000000000000000000000000000; filtb[17] = 0.0483117659859851472647918058100913185626268386840820312500000000000000000000000000000000000000000000; filtb[18] = 0.0440333482528297986968723876088915858417749404907226562500000000000000000000000000000000000000000000; filtb[19] = 0.0392600347372514466015580580915411701425909996032714843750000000000000000000000000000000000000000000; filtb[20] = 0.0341170092244123396296728856214031111449003219604492187500000000000000000000000000000000000000000000; filtb[21] = 0.0287370345711178490355486303542420500889420509338378906250000000000000000000000000000000000000000000; filtb[22] = 0.0232562730997107544594904027235315879806876182556152343750000000000000000000000000000000000000000000; filtb[23] = 0.0178100495406813379151156340185480075888335704803466796875000000000000000000000000000000000000000000; filtb[24] = 0.0125287023096614606038068373550231626722961664199829101562500000000000000000000000000000000000000000; // uses only filtb function applyFIRFilter(srcbuf, destbuf, buflen) ( memset(destbuf,0,filtlen); // assume zeros in output for beginning afidx=filtlen-1; loop(buflen-filtlen+1, newy=srcbuf[afidx]*filtb[0]; fidx=1; loop(filtlen-1, newy += srcbuf[afidx-fidx]*filtb[fidx]; fidx+=1; ); destbuf[afidx]=newy; afidx+=1; ); ); function upsampleBuffer(srcbuf, uslen, usfact, workbuf, destbuf) ( // zero-stuff usidx=0; loop(uslen, workbuf[usidx*usfact]=srcbuf[usidx]; memset(workbuf+usidx*usfact+1,0,usfact-1); usidx+=1; ); // low-pass filter applyFIRFilter(workbuf, destbuf, uslen*usfact); ); upsampleBuffer(input, datasize, upsampfact, work, output); draw=1; @gfx // both graphs are normalized for vertical scale, so if one has a peak or lacks a peak, it might scale unexpectedly gfx_w != lastx || gfx_y != lasty ? draw=1; lastx=gfx_w; lasty=gfx_y; draw ? ( dmin=9999999999999999999; dmax=-dmin; gdidx=0; loop(datasize, dmin=min(dmin, input[gdidx]); dmax=max(dmax, input[gdidx]); gdidx+=1; ); gfx_set(.5,.5,1,.8); gfx_x=0; gfx_y=gfx_h/2; gdidx=-1; loop(datasize, gfx_lineto(gfx_w*(gdidx+=1)/(datasize-1), gfx_h/2-(gfx_h/2)*(2*(input[gdidx]-dmin)/(dmax-dmin)-1))); dmin=9999999999999999999; dmax=-dmin; gdidx=0; loop(datasize*upsampfact, dmin=min(dmin, output[gdidx]); dmax=max(dmax, output[gdidx]); gdidx+=1; ); gfx_set(1,.5,.5,.8); gfx_x=0; gfx_y=gfx_h/2; gdidx=0; loop(datasize*upsampfact, gfx_lineto(gfx_w*(gdidx-(filtlen-1)/2)/(datasize*upsampfact-upsampfact), gfx_h/2-(gfx_h/2)*(2*(output[gdidx]-dmin)/(dmax-dmin)-1)); gdidx+=1; ); gfx_x=5;gfx_y=gfx_h-20; gfx_set(1,1,1,1); gfx_drawstr("Original in blue, upsampled in pink."); draw=0; )