我有一个大学分配,包括使用C++/Qt显示音频文件的波形.我们应该能够修改用于显示它的比例(以每个屏幕像素的音频样本表示).
到目前为止,我能够:
打开音频文件
阅读样本
以给定的比例绘制样本
为了以给定的比例绘制样本,我尝试了两种策略.假设N是比例的值:
因为我从0到窗口的宽度,在屏幕像素i处绘制第i*N个音频样本.这是非常快速和恒定的,因为我们总是访问相同数量的音频数据点.但是,它并不能正确表示波形,因为我们只使用1点的值来表示N点.
因为我从0到N*宽度,在屏幕位置i /(N*宽度)绘制第i个音频样本,让Qt弄清楚如何在物理屏幕像素上正确表示.这绘制了非常漂亮的波形,但访问数据需要花费大量时间.例如,如果我想每像素显示500个样本并且我的窗口宽度是100px,我必须访问50 000个点,然后由Qt绘制为100个物理点(像素).
那么,我怎样才能得到一个正确的音频数据图,可以快速计算出来?我应该计算每个物理像素的N个样本的平均值吗?我应该做一些曲线拟合吗?
换句话说,当Qt/Matplotlib/Matlab /等绘制数千个数据指向非常有限的物理像素时,涉及什么样的操作?
只是因为我知道如何做到这一点,我已经在stackoverflow上问过类似的东西,我会引用它.我稍后会提供代码.
绘制波形是一个真正的问题.我试图解决这个问题超过一年半!总结一下:
根据Audacity文档:
波形视图使用两种蓝色,一种较暗,一种较浅.
波形的深蓝色部分显示像素所代表区域中的最高峰.默认缩放级别Audacity将在该像素宽度内显示许多样本,因此该像素表示组中最响亮的样本的值.
波形的浅蓝色部分显示同一组样本的平均RMS(均方根)值.这是该区域听起来响亮的粗略指南,但无法单独提取或使用此波形的RMS部分.
因此,您只需尝试从一大块数据中获取重要信息.如果你反复这样做,你将有多个阶段可用于绘图.
我会在这里提供一些代码,请耐心等待我的开发:
templateclass CacheHandler { public: std::vector data; vector2d min, max, rms; CacheHandler(std::vector & data) throw(std::exception); void addData(std::vector & samples); /* irreversible removes data. Fails if end index is greater than data length */ void removeData(int endIndex); void removeData(int startIndex, int endIndex); };
使用这个:
templateinline WaveformPane::CacheHandler ::CacheHandler(std::vector & data, int sampleSizeInBits) throw(std::exception) { this->data = data; this->sampleSizeInBits = sampleSizeInBits; int N = log(data.size()) / log(2); rms.resize(N); min.resize(N); max.resize(N); rms[0] = calcRMSSegments(data, 2); min[0] = getMinPitchSegments(data, 2); max[0] = getMaxPitchSegments(data, 2); for (int i = 1; i < N; i++) { rms[i] = calcRMSSegments(rms[i - 1], 2); min[i] = getMinPitchSegments(min[i - 1], 2); max[i] = getMaxPitchSegments(max[i - 1], 2); } }