最近幫別人作了個東西,這裏分享一下pcm原始數據繪圖的思路git
一、pcm數據採樣位數,根據採樣位數選取適合本身繪圖的採樣點的數量github
二、計算出最大最小的的採樣點的值差測試
三、根據要顯示pcm數據的控件寬高,根據pcm原始數據的在pcm數據的偏移計算出x座標,根據pcm數據採樣的數值大小計算出y座標ui
四、繪圖,依次進行相鄰數據點繪圖spa
如下是在Duilb中繪圖的代碼:code
1 std::vector<char> pcm_buffer; 2 FILE * file = NULL; 3 file = fopen("pcm\\20180601155322.pcm", "rb"); 4
5 if (file != NULL) { 6 // 7 pcm_buffer.clear(); 8 pcm_buffer.shrink_to_fit(); 9
10 fseek(file, 0, SEEK_END); 11 unsigned int size_byte = ftell(file); 12 fseek(file, 0, SEEK_SET); 13 pcm_buffer.resize(size_byte); 14 fread(&pcm_buffer[0], size_byte, 1, file); 15 fclose(file); 16 size_byte /= 2; 17 int step = 1, len = size_byte; 18 if (size_byte > 20000) { 19 len = 20000; 20 step = (int)(size_byte / len); 21 } 22 short * pcm_16 = (short*)(&pcm_buffer[0]); 23 std::vector<float> pcm_float; 24 pcm_float.resize(20000); 25 for (int i = 0, n = 0; n < len; i += step, n++) { 26 pcm_float[n] = pcm_16[i]; 27 } 28
29 float max = pcm_float[0], min = pcm_float[0]; 30 for (int i = 1; i< pcm_float.size(); i++){ 31 if (max < pcm_float[i]){ 32 max = pcm_float[i]; 33 } 34 if (min > pcm_float[i]){ 35 min = pcm_float[i]; 36 } 37 } 38 int w = m_rcItem.right - m_rcItem.left; 39 int h = m_rcItem.bottom - m_rcItem.top; 40 std::vector<PointF> points; 41 float diffVal = max - min; 42 for (int i = 0; i < pcm_float.size(); i++){ 43 points.push_back(PointF(i * w / pcm_float.size(), h - (pcm_float[i] - min) / diffVal * h)); 44 } 45
46 const DWORD backColor = 0xFFC9C9C9; 47 CRenderEngine::DrawColor(hDC, m_rcItem, backColor); 48 const DWORD backLineColor = 0xFF0000FF; 49 for (int i = 0; i < points.size() - 1; i++){ 50 RECT rect; 51 rect.left = points[i].X; 52 rect.top = points[i].Y + m_rcItem.top; 53 rect.right = points[i + 1].X; 54 rect.bottom = points[i + 1].Y + m_rcItem.top; 55 CRenderEngine::DrawLine(hDC, rect, 1, backLineColor); 56 } 57 }
繪圖效果:blog
測試繪圖代碼: https://github.com/karllen/cef3-duilib-YDDemo/tree/master/PcmMediaDemo
get