Shif.
The aliasing thread
- KVRian
- 1305 posts since 12 Nov, 2002 from Newcastle, UK
This has been a very interesting thread
A little question (easy to answer
) what software are you using to display the .wavs in the frequency domain - i.e. to get the images?
Shif.
Shif.
-
- KVRist
- 190 posts since 28 Nov, 2003
- Banned
- 5089 posts since 12 Jun, 2001 from Wusik Dot Com
-
- KVRist
- 190 posts since 28 Nov, 2003
hmm. i wish audacity had a better spectrogram view, though it is definitely improving.
-
tony tony chopper tony tony chopper https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=3103
- KVRAF
- 3561 posts since 20 Jun, 2002
It's not 'realtime' here, but I also don't do anything below 128 points (64 on each side that is). With 128 points (& stereo) it uses 15% of my AMD 1700. That's without any SSE or 3DNow, and without optimizations of the loop points checks.What I consider 'useable realtime' is something that allows me do the same as an average hardware sampler: playing 48~64 voices realtime before the CPU explodes. If I can't play a decent piano realtime, it's not for me. I feel it like what CSound is to a VSTi.
So this is arguru's sinc with an added groetzthing for the sines. I first tried a huge non-interpolated sine table but it didn't work.
Code: Select all
function StretchWave_Sinc_16IS_32FS(var StretchParams:TStretchParams;DestBuffer:PWAV32FS;Length:Integer):Integer;
const DivAdd:Single=Pi;
var n,e,l,PtNum,x:Integer;
LSum,RSum,k_fcpi,SinCB:Single;
DivV,Sin1,Sin2,Cos1,Cos2:Array[0..1] of Single;
v,v2:Double;
p:PWAV16IS;
SampleP:PWORD;
b:Boolean;
Label NoBefore,NoAfter;
Begin
with StretchParams do
Begin
v:=1/(IntAdd+LongWord(FracAdd)*MaxDWORDToFloat);
if v>1 then v:=1;
k_fcpi:=v*Pi;
SinCB:=2*Cos(k_fcpi);
e:=LoopStart;
l:=LoopEnd-e+1;
for n:=0 to Length-1 do
Begin
// process
p:=Pointer(WAVP+IntPos shl 2);
LSum:=0;
RSum:=0;
b:=LoopCount<=0;
if FracPos=0 then v:=MaxDWORDToFloat
else v:=LongWord(FracPos)*MaxDWORDToFloat;
// cos
v2 :=v*SincDiv;
Cos1 [0]:=Cos(v2+SincDiv);
Cos2 [0]:=Cos(v2);
v2 :=v2-SincDiv;
Cos1 [1]:=Cos(v2-SincDiv);
Cos2 [1]:=Cos(v2);
// sin
v2 :=v*k_fcpi;
Sin1 [0]:=Sin(v2+k_fcpi);
Sin2 [0]:=Sin(v2);
v2 :=v2-k_fcpi;
Sin1 [1]:=Sin(v2-k_fcpi);
Sin2 [1]:=Sin(v2);
// div (none should be zero if written that way)
DivV [0]:=v*DivAdd;
DivV [1]:=(v-1)*DivAdd;
// calc the sum
for PtNum:=0 to Sinc_nPoints-1 do
Begin
// before
x:=-PtNum;
if b then
Begin
if x+IntPos<0 then GoTo NoBefore;
End
else
while x+IntPos<e do inc(x,l);
SampleP:=@p^[x,0];
{
s:=Sin2[0]*Cos2[0]*Cos2[0]/DivV[0];
LSum:=LSum+p^[x,0]*s;
RSum:=RSum+p^[x,1]*s;
// cos
s :=CosCB*Cos1[0]-Cos2[0];
Cos2[0]:=Cos1[0];
Cos1[0]:=s;
// sin
s :=SinCB*Sin1[0]-Sin2[0];
Sin2[0]:=Sin1[0];
Sin1[0]:=s;
// div
DivV[0]:=DivV[0]+DivAdd;
}
asm
// cos
FLD DWORD PTR Cos2[0]
FLD DWORD PTR Cos1[0]
FST DWORD PTR Cos2[0]
FMUL DWORD PTR CosCB
FSUB ST(0),ST(1)
FSTP DWORD PTR Cos1[0]
FMUL ST(0),ST(0) // s (Cos2*Cos2)
// sin
FLD DWORD PTR Sin2[0]
FLD DWORD PTR Sin1[0]
FST DWORD PTR Sin2[0]
FMUL DWORD PTR SinCB
FSUB ST(0),ST(1)
FSTP DWORD PTR Sin1[0]
FMULP ST(1),ST(0) // s (*Sin2)
// div
FLD DWORD PTR DivV[0]
FDIV ST(1),ST(0) // s (/DivV)
FADD DivAdd
FSTP DWORD PTR DivV[0]
//FSTP s
// LSum
MOV EAX,SampleP
FILD WORD PTR [EAX]
FMUL ST(0),ST(1)
FADD LSum
FSTP LSum
// RSum
FILD WORD PTR [EAX+2]
FMUL ST(0),ST(1)
FADD RSum
FSTP RSum
FSTP ST(0)
End;
NoBefore:
// after
x:=PtNum+1;
if x+IntPos>EndPos then
Begin
if LoopLength<=0 then GoTo NoAfter
else
Repeat
dec(x,LoopLength);
Until x+IntPos<=EndPos;
End;
SampleP:=@p^[x,0];
{
s:=Sin2[1]*Cos2[1]*Cos2[1]/DivV[1];
LSum:=LSum+p^[x,0]*s;
RSum:=RSum+p^[x,1]*s;
// cos
s :=CosCB*Cos1[1]-Cos2[1];
Cos2[1]:=Cos1[1];
Cos1[1]:=s;
// sin
s :=SinCB*Sin1[1]-Sin2[1];
Sin2[1]:=Sin1[1];
Sin1[1]:=s;
// div
DivV[1]:=DivV[1]-DivAdd;
}
asm
// cos
FLD DWORD PTR Cos2[4]
FLD DWORD PTR Cos1[4]
FST DWORD PTR Cos2[4]
FMUL DWORD PTR CosCB
FSUB ST(0),ST(1)
FSTP DWORD PTR Cos1[4]
FMUL ST(0),ST(0) // s (Cos2*Cos2)
// sin
FLD DWORD PTR Sin2[4]
FLD DWORD PTR Sin1[4]
FST DWORD PTR Sin2[4]
FMUL DWORD PTR SinCB
FSUB ST(0),ST(1)
FSTP DWORD PTR Sin1[4]
FMULP ST(1),ST(0) // s (*Sin2)
// div
FLD DWORD PTR DivV[4]
FDIV ST(1),ST(0) // s (/DivV)
FSUB DivAdd
FSTP DWORD PTR DivV[4]
//FSTP s
// LSum
MOV EAX,SampleP
FILD WORD PTR [EAX]
FMUL ST(0),ST(1)
FADD LSum
FSTP LSum
// RSum
FILD WORD PTR [EAX+2]
FMUL ST(0),ST(1)
FADD RSum
FSTP RSum
FSTP ST(0)
End;
NoAfter:
End;
// store it
DestBuffer^[n,0]:=LSum*IntToFloatVar;
DestBuffer^[n,1]:=RSum*IntToFloatVar;
// inc the position
StretchParams_Inc(StretchParams);
// check the loop points
while IntPos>EndPos do
if LoopLength<=0 then
Begin
Result:=n+1;
Exit;
End
else
Begin
dec(IntPos,LoopLength);
inc(LoopCount);
End;
End;
End;
Result:=Length;
End;
Last edited by tony tony chopper on Mon Sep 20, 2004 5:08 am, edited 1 time in total.
-
tony tony chopper tony tony chopper https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=3103
- KVRAF
- 3561 posts since 20 Jun, 2002
is it new? (not that I understand it)Here's another implementation of sinc resampler
- u-he
- 30213 posts since 8 Aug, 2002 from Berlin
Another funny idea:
One keeps 2 tables of precalculated, pre-windowed sines and cosines for the sinc, at arbitrary frequency. With Goertzl (or a look at Musicdsp) you can just phaseshift these to fit the fractional position.
Dunno how to do the reciprocal part of the sinc though. I guess I need another coffee first...
Cheers,
Urs
One keeps 2 tables of precalculated, pre-windowed sines and cosines for the sinc, at arbitrary frequency. With Goertzl (or a look at Musicdsp) you can just phaseshift these to fit the fractional position.
Dunno how to do the reciprocal part of the sinc though. I guess I need another coffee first...
Cheers,
-
- KVRist
- 32 posts since 22 Sep, 2004 from Melbourne, Australia
I may be insane
(both medically and legally) but I think I have a new (as far as I can tell) way to resample inside a sampler plugin. It's backwards because I oversample, resample and interpolate in one step, then I filter with a windowed sinc FIR filter with cutoff fixed at the nyquist frequency of the non-oversampled data. So, even if a sample's rate is not changed, I will be removing aliasing. I also only need one FIR per plugin, not per voice, as each voice can output oversampled data, the plugin mixes these and then brick wall filters them, then downsamples.
Neat huh? What do you think
I have tried plotting what happens to a naive (aliased) square wave, and it looks great, I just need to implement my soundfont loader and my sampler and I will be able to hear how useful it is. (I like playing with sfz loaded into my host DarkWave Studio, maybe I'll use that for ear comparisons).
Neat huh? What do you think
I have tried plotting what happens to a naive (aliased) square wave, and it looks great, I just need to implement my soundfont loader and my sampler and I will be able to hear how useful it is. (I like playing with sfz loaded into my host DarkWave Studio, maybe I'll use that for ear comparisons).
-
Fire Sledge - Ohm Force Fire Sledge - Ohm Force https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=46
- KVRist
- 121 posts since 2 Nov, 2000 from 404 - Not found
But how do you oversample ? With a FIR too ?dwerner wrote:I oversample, resample and interpolate in one step, then I filter with a windowed sinc FIR filter with cutoff fixed at the nyquist frequency of the non-oversampled data. So, even if a sample's rate is not changed, I will be removing aliasing. I also only need one FIR per plugin, not per voice, as each voice can output oversampled data, the plugin mixes these and then brick wall filters them, then downsamples.
-
- KVRist
- 32 posts since 22 Sep, 2004 from Melbourne, Australia
Basically I resample and oversample at the same time (unless oversampling is disabled in which case I just resample) using linear or 4-point lagrange interpolation, no FIR yet. This will of course introduce aliasing (especially for linear) so I then hope to filter it out with the FIR. Haven't heard it working yet but I think it should be good.Fire Sledge - Ohm Force wrote:But how do you oversample ? With a FIR too ?
-
- KVRist
- 32 posts since 22 Sep, 2004 from Melbourne, Australia
Hmmm... It's in the alpha stage, it is missing a LOT of features and some features only half work, but what the hell I think I'll put it up for download, go to my site it should be up for download when you read this .Scr1pt3r wrote:dwerner , is your host available for download ?
never heard of it before.
-
- KVRist
- 32 posts since 22 Sep, 2004 from Melbourne, Australia
Maybe I wasn't too clear in that post: There is only a FIR filtering at the higher samplerate *after* interpolation, no FIR during the interpolation process.dwerner wrote: Basically I resample and oversample at the same time (unless oversampling is disabled in which case I just resample) using linear or 4-point lagrange interpolation, no FIR yet. This will of course introduce aliasing (especially for linear) so I then hope to filter it out with the FIR. Haven't heard it working yet but I think it should be good.
-
- KVRAF
- 1907 posts since 29 Oct, 2003
just curious: anybody tested cm DS404 ? why not?
-
- KVRAF
- 2988 posts since 11 Apr, 2001
It does work, and that's how it's implemented in several synthesizers (including Pentagon I and z3ta+). The plugins process everything at an 'internal' oversample rate, then a single fir is used at the end of the chain after voice mixing.I oversample, resample and interpolate in one step, then I filter with a windowed sinc FIR filter with cutoff fixed at the nyquist frequency of the non-oversampled data. So, even if a sample's rate is not changed, I will be removing aliasing. I also only need one FIR per plugin, not per voice, as each voice can output oversampled data, the plugin mixes these and then brick wall filters them, then downsamples.
The major drawback of the system is that every dsp process after sample playing must be processed at Nx the samplerate, and some of those processes won't get any benefit from the oversampling process.
For instance, the amp envelope control, the filters, etc. have to be processed at Nx the original samplerate. Depending on how many of those processes follow the sample playback, this might cost much more than having a per-voice resampler in terms of CPU usage.
The requirements for the output fir can be minimized by using the Nyquist - 20kHz area as passband area.
-René

