Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Rightclick on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
From: Antti S. Lankila <alankila@be...>  20060707 11:15:55

I am looking for an usable wave viewer. I am interested in the details of the waveform, and it's crucial that I can see exactly what each particular sample is. kwave is simple enough for my purposes, but it has got interpolation which is on the way of making sense of what the samples *really* are. Can the sample display be easily improved in the following ways:  show each actual measured sample as bright white dot  render a line that connects the dots but make it darker gray so that the white sample points can at all times be seen. The above is crucial, because the line is simply noise to me, I always wish to see the samples, and this feature is simply essential. Another important point is that linear interpolation, or any other interpolation, is not even correct. If this could be fixed, I'd be one happy man. Additionally, it would be nice to also have signaltheoretically correct sincbased interpolation in case someone really wants to see the interpolated waveform. Sinc interpolation should be fairly close to how real analog hardware tasked with representing the signal might render it, although it will probably not reproduce the phase errors that the analog systems will make. Regardless, it'd much more correct than any of the interpolations currently coded in: linear interpolation, various degrees of polynomials, spline or sampleandhold. I can describe how that interpolation works, but I'm probably not able to implement it in C++. I can, regardless, validate that output is correct if someone else is up to the task. The basic idea is to weigh each sample around the interpolation point with a weight that is computed from the sinc function. sinc is basically a digital filter that has flat passband and infinitely attenuated stopband (in theory). In practice we'll have to compromise with these properties somewhat, but the performance will be much better than with the other interpolators anyway. Sinc itself introduces a distortion known as preringing (and postringing), where the interpolated sample waveform will appear to "anticipate" large transitions and will begin to oscillate a few samples before they actually occur. This is just a property of bandlimited linearphase interpolation, and nothing should be done about it; it is normal. On to implementation. Firstly, the sinc function is defined as: sin(x * pi) / (x * pi) It has the property that it is 1 for x = 0, and 0 for every other integer value of x. The value of x physically means "distance in samples from to the interpolation point to the sample we are weighing". How we use it is, we calculate the convolution (= sum of multiplications between sinc function and the sample data) of sinc function against the sample data over some small part of the sample stream, for instance, we could use the previous 8 samples and the next 8 samples for each inbetween interpolation point. This would be called 16tap FIR in literature. An example may illuminate this point. For instance, if we are interpolating a sample exactly at the point where measurement is known, the distance to current sample will be 0 (where sinc evaluates to 1), and distance to every other sample will be some positive or negative integer (where sinc evauates to 0). Therefore it follows that the interpolation on top of a sample point yields the sample itself, thus we know interpolated curve must pass through every sample. If we move, say, 0.1 samples to right, then the distances to samples on the right side will be 0.9, 1.9, 2.9, 3.9 and so on, and the distances to the samples on the left side will be 0.1, 1.1, 2.1, 3.1, and so on. The values needed from the sinc function will thus be those values. At this point, sinc will no longer evaluate to zero on either side of the waveform, and every sample on the 16tap area will contribute to the value of interpolation at that point. A final point to consider with sinc interpolation is that the sinc oscillates from negative infinity to positive infinity. We can assume that for our purposes the sinc function has damped enough by the time we reach the 8th sample on either side, and we can ignore the fact that the trailing edge of the sinc function is not exactly zero yet. However, if desired, windowing function such as the Hann window can be used to properly curb the sinc oscillations. This should further improve the accuracy of the interpolation, although I doubt anyone looking at the interpolated curve could tell.  Antti 
From: Thomas Eschenbacher <Thomas.Eschenbacher@gm...>  20060707 16:06:42

Antti S. Lankila wrote: > I am looking for an usable wave viewer. I am interested in the details > of the waveform, and it's crucial that I can see exactly what each > particular sample is. kwave is simple enough for my purposes, but it has > got interpolation which is on the way of making sense of what the > samples *really* are. > > Can the sample display be easily improved in the following ways: > >  show each actual measured sample as bright white dot just increase the zoom factor and you should see each sample. >  render a line that connects the dots but make it darker gray so that > the white sample points can at all times be seen. This is exactly what Kwave already does!? Well, maybe the contrast between the white and the gray I use is too small, but that's easy to change... > The above is crucial, because the line is simply noise to me, I always > wish to see the samples, and this feature is simply essential. Another > important point is that linear interpolation, or any other > interpolation, is not even correct. Kwave uses three different modes for sample display, depending on the zoom factor: 1. overview mode: collect "n" samples, build minimum/maximum and display it as a vertival line (white). 2. poly line mode: do not interpolate, just connect samples (white) with lines (dark gray) 3. interpolated mode: draw a low pass interpolated signal (dark gray) with the original samples hilighted (white). I have spent a lot of time in this and IMO this is what you are asking for. I currently use a simple low pass filter with variable order depending on the zoom factor, with a hamming window: > sin( (2kN) * Pi * Fg ) 2kPi > alpha_k = 2 * Fg *  * [ 0,54  0,46 * cos  ] > (2k  N) * Pi * Fg N This worked good enough for my purpose. If you are interested: look into libgui/TrackPixmap.cpp, here you will see how samples are rendered into a bitmap! especially the functions TrackPixmap::calculateInterpolation() and TrackPixmap::drawInterpolatedSignal() Your description sounds very interesting and I think I understood the idea behind it... > > The basic idea is to weigh each sample around the interpolation point > with a weight that is computed from the sinc function. sinc is basically > a digital filter that has flat passband and infinitely attenuated > stopband (in theory). In practice we'll have to compromise with these > properties somewhat, but the performance will be much better than with > the other interpolators anyway. > > Sinc itself introduces a distortion known as preringing (and > postringing), where the interpolated sample waveform will appear to > "anticipate" large transitions and will begin to oscillate a few samples > before they actually occur. This is just a property of bandlimited > linearphase interpolation, and nothing should be done about it; it is > normal. yes, and depends on the cutoff frequency. I preferred using a quite low cutoff frequency that produces 3dB at f_max/2 to produce a smooth display without pre and postringing which produces pixels which are out of the display area > and therefore do not look realistic. This was a hard requirement for me, so I have to use something with an impulse response that behaves rather like a bessel filter... > On to implementation. Firstly, the sinc function is defined as: > > sin(x * pi) / (x * pi) > > It has the property that it is 1 for x = 0, and 0 for every other > integer value of x. Sounds familiar to me, like a simple inverse fourier transformation. > The value of x physically means "distance in samples from to the > interpolation point to the sample we are weighing". How we use it is, > we calculate the convolution (= sum of multiplications between sinc > function and the sample data) of sinc function against the sample data > over some small part of the sample stream, for instance, we could use > the previous 8 samples and the next 8 samples for each inbetween > interpolation point. This would be called 16tap FIR in literature. You are passing a time shifted dirac impulse through a FIR, so far ok. FIR is fine as I do not like oscillations / cannot accept an infinite impulse response. > [...] > A final point to consider with sinc interpolation is that the sinc > oscillates from negative infinity to positive infinity. We can assume > that for our purposes the sinc function has damped enough by the time we > reach the 8th sample on either side, and we can ignore the fact that the > trailing edge of the sinc function is not exactly zero yet. However, if > desired, windowing function such as the Hann window can be used to > properly curb the sinc oscillations. This should further improve the > accuracy of the interpolation, although I doubt anyone looking at the > interpolated curve could tell. As far as I have learned, the ideal interpolation does not exist in practice. It would require an ideal lowpass with border frequency at sample_rate/2 and infinite order. I already have done a lot of experiments with different filter coefficients and orders. If you think you can give me a better algorithm or filter function you are welcome ;) So, what exactly do you suggest? regards, Thomas 
Sign up for the SourceForge newsletter:
No, thanks