I'm not a Java programmer, but I know a fair bit about rendering audio so hopefully the following might be of some help...
Given that you will almost always have a much larger number of samples than available pixels the sensible thing to do would be to draw from a cached reduction or 'summary' of the sample data. This is typically how audio editors (such as Audacity) render audio data. In fact the most common strategy is to compute the number of samples per pixel, then find the maximum and minimum samples for each block of size SamplesPerPixel
, then draw a vertical line between each max-min pair. You might want to cache this reduction, or perhaps a series of such reductions for different zoom levels. Audacity caches to temporary files ('block files') on disk.
The above is perhaps something of an oversimplification, however, because in reality you will want to compute the initial max-min pairs from a chunk of fixed size - say 256 samples - rather than from one of size SamplesPerPixel
. Then you can compute further 'on the fly' reductions from that cached reduction. The point is that SamplesPerPixel
will typically be a dynamic quantity - since the user might resize the canvas at any time (hope that makes sense...).
Also remember that when you are drawing to your canvas you will need to scale the sample values by the width and height of the canvas. The best way to do this (in the vertical direction, at least) is to normalize the samples, then multiply by the canvas height. 16-bit audio consists of samples in the range [-32768, 32767], so to normalize just do a floating-point division by 32768. Then reverse the sign (to flip the waveform to the canvas coordinates), add 1 (to compensate for the negative values) and multiply by half the canvas height. That's how I do it, anyway.
This page shows how to build a rudimentary waveform display with Java Swing. I haven't looked at it in detail, but I think it just downsamples the data rather than computing max-min pairs. This will, of course, not provide as accurate a reduction as the max-min method, but it's easier to calculate.
If you want to know how to do things properly you should dig into the Audacity source code (be warned, however - it's fairly gnarly C++). To get a general overview you might look at 'A Fast Data Structure for Disk-Based Audio Editing', by the original author of Audacity, Dominic Mazzoni. You will need to purchase that from CMJ, however.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…