我的建议是这样的:
给定音频文件中的totalNumSamples 音频样本和显示小部件中的widgetWidth 像素宽度,您可以计算每个像素代表哪些样本:
// Given an x value (in pixels), returns the appropriate corresponding
// offset into the audio-samples array that represents the
// first sample that should be included in that pixel.
int GetFirstSampleIndexForPixel(int x, int widgetWidth, int totalNumSamples)
{
return (totalNumSamples*x)/widgetWidth;
}
virtual void paintEvent(QPaintEvent * e)
{
QPainter p(this);
for (int x=0; x<widgetWidth; x++)
{
const int firstSampleIndexForPixel = GetFirstSampleIndexForPixel(x, widgetWidth, totalNumSamples);
const int lastSampleIndexForPixel = GetFirstSampleIndexForPixel(x+1, widgetWidth, totalNumSamples)-1;
const int largestSampleValueForPixel = GetMaximumSampleValueInRange(firstSampleIndexForPixel, lastSampleIndexForPixel);
const int smallestSampleValueForPixel = GetMinimumSampleValueInRange(firstSampleIndexForPixel, lastSampleIndexForPixel);
// draw a vertical line spanning all sample values that are contained in this pixel
p.drawLine(x, GetYValueForSampleValue(largestSampleValueForPixel), x, GetYValueForSampleValue(smallestSampleValueForPixel));
}
}
请注意,我没有包含 GetMinimumSampleValueInRange()、GetMaximumSampleValueInRange() 或 GetYValueForSampleValue() 的源代码,因为希望它们的作用从它们的名称中显而易见,但如果没有,请告诉我,我可以解释它们。
一旦您使上述工作相当顺利(即在小部件中绘制显示整个文件的波形),您就可以开始添加缩放和平移功能了。水平缩放可以通过修改GetFirstSampleIndexForPixel()的行为来实现,例如:
int GetFirstSampleIndexForPixel(int x, int widgetWidth, int sampleIndexAtLeftEdgeOfWidget, int sampleIndexAfterRightEdgeOfWidget)
{
int numSamplesToDisplay = sampleIndexAfterRightEdgeOfWidget-sampleIndexAtLeftEdgeOfWidget;
return sampleIndexAtLeftEdgeOfWidget+((numSamplesToDisplay*x)/widgetWidth);
}
这样,您可以简单地通过为sampleIndexAtLeftEdgeOfWidget 和sampleIndexAfterRightEdgeOfWidget 传递不同的值来缩放/平移,这些值共同指示您要显示的文件的子范围。