画一个示波器界面,显示麦克风采集到的声音数据

用一个示波器的BMP图做背景,在上面画出麦克风采集到的数据. 只是数据看起好奇怪。似乎只有密度变化,没有幅度变化。

升级到VS2022了,字符串处理又有些不同了。似乎更严格了。

 

 

程序 Wave.cpp

// WAVE.cpp : Defines the entry point for the application.
// 画一个示波器界面,显示麦克风采集到的声音数据
// XGZ 2022-05-27 SZ

#include "pch.h"
#include "framework.h"
#include "WAVE.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

//xgz==========
#define IDC_EDIT               1001 
#define IDC_BUTTON1        1002
#define IDC_BUTTON2        1003
#define IDC_BUTTON3        1004
#define IDC_BUTTON4        1005
#define IDC_BUTTON5        1006
#define IDC_BUTTON6        1007

HWND hWndEdit;

HWND hWndButton1;
HWND hWndButton2;
HWND hWndButton3;
HWND hWndButton4;
HWND hWndButton5;
HWND hWndButton6;

int OnCreate(HWND, UINT, WPARAM, LPARAM);
int OnSize(HWND, UINT, WPARAM, LPARAM);
int OnPaint(HWND, UINT, WPARAM, LPARAM);
int OnTimer(HWND, UINT, WPARAM, LPARAM);

int OnButton1(HWND, UINT, WPARAM, LPARAM);
int OnButton2(HWND, UINT, WPARAM, LPARAM);
int OnButton3(HWND, UINT, WPARAM, LPARAM);
int OnButton4(HWND, UINT, WPARAM, LPARAM);
int OnButton5(HWND, UINT, WPARAM, LPARAM);
int OnButton6(HWND, UINT, WPARAM, LPARAM);


int PRINT(const TCHAR * fmt, ...)
{
    TCHAR buffer[1024];

    va_list argptr;
    int cnt;

    int iEditTextLength;
    HWND hWnd = hWndEdit;

    if (NULL == hWnd) return 0;

    va_start(argptr, fmt);
    cnt = wvsprintf(buffer, fmt, argptr);  // not %f
    
    va_end(argptr);

    iEditTextLength = GetWindowTextLength(hWnd);
    if (iEditTextLength + cnt > 30000)       // edit text max length is 30000
    {
        SendMessage(hWnd, EM_SETSEL, 0, 10000);
        SendMessage(hWnd, WM_CLEAR, 0, 0);
        iEditTextLength = iEditTextLength - 10000;
    }
    SendMessage(hWnd, EM_SETSEL, iEditTextLength, iEditTextLength);
    SendMessage(hWnd, EM_REPLACESEL, 0, (LPARAM)buffer);

    return(cnt);
}

//==D Show===============
//#include <atlbase.h>
//#include <dshow.h>
//#pragma comment(lib,"Strmiids.lib")

#include <atlstr.h>
#include <Mmsystem.h>
#pragma comment(lib,"Winmm.lib")


HWND m_hWnd=NULL;

DWORD datasize = 48000;
char* pBuffer1 = NULL;   //XGZ 2022-05-29 改成 unsigned char 
WAVEFORMATEX    waveformat;
HWAVEOUT        hWaveOut;
HWAVEIN            hWaveIn;
WAVEHDR            m_pWaveHdr1;
WAVEHDR            m_pWaveHdr;
int                res;

HBITMAP m_hBitmap_mem;
HBITMAP m_hBitmap_mem0;
HDC hdcmem;
HDC hdcmem0;
HDC m_hdc_mem;
HDC m_hdc_mem0;
HPEN hPen, hPenW;
HBRUSH hBrush;

int displayBK(HWND hWnd);
int displayWave(HWND hWnd);

int iStart = 0;
VOID ThreadProc1(PVOID pData);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_WAVE, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WAVE));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}


ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WAVE));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WAVE);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}


BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   m_hWnd = hWnd;

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_CREATE:
        OnCreate(hWnd, message, wParam, lParam);
        break;
    case WM_SIZE:
        OnSize(hWnd, message, wParam, lParam);
        break;
    case WM_PAINT:
        OnPaint(hWnd, message, wParam, lParam);
        break;
    case WM_TIMER:
        OnTimer(hWnd, message, wParam, lParam);
        break;
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDC_BUTTON1:
            OnButton1(hWnd, message, wParam, lParam);
            break;
        case IDC_BUTTON2:
            OnButton2(hWnd, message, wParam, lParam);
            break;
        case IDC_BUTTON3:
            OnButton3(hWnd, message, wParam, lParam);
            break;
        case IDC_BUTTON4:
            OnButton4(hWnd, message, wParam, lParam);
            break;
        case IDC_BUTTON5:
            OnButton5(hWnd, message, wParam, lParam);
            break;
        case IDC_BUTTON6:
            OnButton6(hWnd, message, wParam, lParam);
            break;
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

int OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    hWndEdit = CreateWindow(_T("edit"), NULL,
        WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL,
        0, 0, 0, 0, hWnd, (HMENU)IDC_EDIT, hInst, NULL);

    hWndButton1 = CreateWindow(_T("button"), _T("1"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);
    hWndButton2 = CreateWindow(_T("button"), _T("2"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON2, hInst, NULL);
    hWndButton3 = CreateWindow(_T("button"), _T("3"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON3, hInst, NULL);
    hWndButton4 = CreateWindow(_T("button"), _T("4"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON4, hInst, NULL);
    hWndButton5 = CreateWindow(_T("button"), _T("5"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON5, hInst, NULL);
    hWndButton6 = CreateWindow(_T("button"), _T("6"),
        WS_CHILD | WS_VISIBLE | BS_FLAT, 0, 0, 0, 0, hWnd, (HMENU)IDC_BUTTON6, hInst, NULL);

    displayBK(hWnd);

    SetTimer(hWnd, 1, 10000, NULL);   //10s

    return 1;
}

//留一个状态条的位置
int OnSize(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int cxClient, cyClient;

    cxClient = LOWORD(lParam);
    cyClient = HIWORD(lParam);

    MoveWindow(hWndEdit, 0, cyClient - 120, cxClient - 50, 100, TRUE);

    MoveWindow(hWndButton1, cxClient - 50, 0, 50, 20, TRUE);
    MoveWindow(hWndButton2, cxClient - 50, 20, 50, 20, TRUE);
    MoveWindow(hWndButton3, cxClient - 50, 40, 50, 20, TRUE);
    MoveWindow(hWndButton4, cxClient - 50, 60, 50, 20, TRUE);
    MoveWindow(hWndButton5, cxClient - 50, 80, 50, 20, TRUE);
    MoveWindow(hWndButton6, cxClient - 50, 100, 50, 20, TRUE);

    return DefWindowProc(hWnd, message, wParam, lParam);

}

int OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rt;

    hdc = BeginPaint(hWnd, &ps);
    GetClientRect(hWnd, &rt);
    //DrawText(hdc, StatusText, strlen(StatusText), &rt, DT_LEFT|DT_BOTTOM|DT_SINGLELINE);
    EndPaint(hWnd, &ps);

    return 1;
}

int OnTimer(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return 1;
}

int OnButton1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    PRINT(_T("\r\n OnButton1"));
    //display(hWnd);
    if (iStart == 0)
    {
        pBuffer1 = new char[datasize];
        iStart = 1;
        _beginthread(ThreadProc1, 0, NULL);
    }
    else
    {
        iStart = 0;
        if (GlobalFree(GlobalHandle(m_pWaveHdr.lpData)))
        {
            PRINT(_T("\r\n Fail: GlobalFree"));
        }
        else
        {
            PRINT(_T("\r\n OK: GlobalFree"));
            return 0;
        }

        if (res == MMSYSERR_NOERROR) // 关闭录音设备
        {
            if (waveInClose(hWaveIn) == MMSYSERR_NOERROR)
            {
                PRINT(_T("\r\n OK: waveInClose"));
            }
            else
            {
                 PRINT(_T("\r\n Fail: waveInClose"));
                return 0;
            }
        }

        delete pBuffer1;

        pBuffer1 = NULL;

    }

    return 1;
}
int OnButton2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PRINT(_T("\r\n OnButton2"));
    

    return 1;
}
int OnButton3(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PRINT(_T("\r\n OnButton3"));
    
    return 1;
}

int OnButton4(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PRINT(_T("\r\n OnButton4 "));
    
    return 1;
}
int OnButton5(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PRINT(_T("\r\n OnButton5 "));
    
    return 1;
}

int OnButton6(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PRINT(_T("\r\n OnButton6 "));
    
    return 1;
}


int displayBK(HWND hWnd)
{
    double x, y;
    POINT pt;
    int i, j, k;

    HDC hdc = GetDC(hWnd);
    HANDLE hh = LoadImage(NULL, _T("wave.bmp"), IMAGE_BITMAP, 500, 350, LR_LOADFROMFILE);
    hdcmem = CreateCompatibleDC(hdc);
    SelectObject(hdcmem, hh);
    
    BitBlt(hdc, 0, 0, 500, 350, hdcmem, 0, 0, SRCCOPY);

    m_hBitmap_mem0 = CreateCompatibleBitmap(hdc, 400, 300);
    m_hdc_mem0 = CreateCompatibleDC(hdc);
    SelectObject(m_hdc_mem0, m_hBitmap_mem0);

    m_hBitmap_mem = CreateCompatibleBitmap(hdc, 400, 300);
    m_hdc_mem = CreateCompatibleDC(hdc);
    SelectObject(m_hdc_mem, m_hBitmap_mem);

    hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
    SelectObject(m_hdc_mem0, hBrush);
    Rectangle(m_hdc_mem0, 0, 0, 400, 300);

    //BLACK_BRUSH
    SetBkMode(m_hdc_mem0, TRANSPARENT);
    hPen = CreatePen(PS_DOT, 1, RGB(100, 100, 100));
    SelectObject(m_hdc_mem0, hPen);

    hPenW = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));
    SelectObject(m_hdc_mem, hPenW);
        
    for (i = 0; i < 300; i += 30)
    {
        MoveToEx(m_hdc_mem0, 0, i, &pt);
        LineTo(m_hdc_mem0, 400, i);
    }

    for (i = 0; i < 400; i += 30)
    {
        MoveToEx(m_hdc_mem0, i, 0, &pt);
        LineTo(m_hdc_mem0, i, 300);
    }
    return 1;
}


int displayWave(HWND hWnd)
{
    double x, y;
    POINT pt;
    
    int i, j, k;

    HDC hdc = GetDC(hWnd);
    BitBlt(hdc, 0, 0, 500, 350, hdcmem, 0, 0, SRCCOPY);

    int dwNumber = m_pWaveHdr.dwBytesRecorded;
BitBlt(m_hdc_mem,
0, 0, 400, 300, m_hdc_mem0, 0, 0, SRCCOPY); MoveToEx(m_hdc_mem, 0, 0, &pt); for (i = 0; i < dwNumber; i++) { x = i; y = *(pBuffer1+i); j = y * 0.3 + 100; LineTo(m_hdc_mem, i, j); } BitBlt(hdc, 28, 30, 370, 180, m_hdc_mem, 0, 0, SRCCOPY); return 1; } int sample(HWND hWnd) { waveformat.wFormatTag = WAVE_FORMAT_PCM; waveformat.nChannels = 1; waveformat.nSamplesPerSec = 8000; waveformat.nBlockAlign = 1; waveformat.wBitsPerSample = 8; waveformat.cbSize = 0; waveformat.nAvgBytesPerSec = waveformat.nChannels * waveformat.nSamplesPerSec * waveformat.wBitsPerSample / 8; if (!waveInGetNumDevs()) { PRINT(_T("\r\n Fail waveInGetNumDevs ")); return 0; } int res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveformat, (DWORD)NULL, 0L, CALLBACK_WINDOW); if (res != MMSYSERR_NOERROR) { PRINT(_T("\r\n Fail: waveInOpen,Error_Code = 0x%x"), res); return 0; } m_pWaveHdr.lpData = pBuffer1; memset(m_pWaveHdr.lpData, 0, datasize); m_pWaveHdr.dwBufferLength = datasize; m_pWaveHdr.dwBytesRecorded = 0; m_pWaveHdr.dwUser = 0; m_pWaveHdr.dwFlags = 0; m_pWaveHdr.dwLoops = 0; int resPrepare = waveInPrepareHeader(hWaveIn, &m_pWaveHdr, sizeof(WAVEHDR)); if (resPrepare != MMSYSERR_NOERROR) { PRINT(_T("\r\n Fail: waveInPrepareHeader,Error_Code = 0x%03X"), resPrepare); return 0; } resPrepare = waveInAddBuffer(hWaveIn, &m_pWaveHdr, sizeof(WAVEHDR)); if (resPrepare != MMSYSERR_NOERROR) { PRINT(_T("\r\n Fail:waveInAddBuffer,Error_Code = 0x%03X"), resPrepare); return 0; } if (!waveInStart(hWaveIn)) { //PRINT(_T("\r\n OK:waveInStart!")); } else { PRINT(_T("\r\n Fail:waveInStart!")); return 0; } Sleep(100); MMTIME mmt; mmt.wType = TIME_BYTES; if (!waveInGetPosition(hWaveIn, &mmt, sizeof(MMTIME))) { } else { PRINT(_T("\r\n Fail:waveInGetPosition!")); return 0; } if (mmt.wType != TIME_BYTES) { PRINT(_T("\r\n Fail:mmt.wType != TIME_BYTES")); return 0; } if (!waveInStop(hWaveIn)) { } else { PRINT(_T("\r\n Fail:waveInStop")); } if (waveInReset(hWaveIn)) { PRINT(_T("\r\n Fail:waveInReset")); return 0; } m_pWaveHdr.dwBytesRecorded = mmt.u.cb; DWORD NumToWrite = 0; DWORD dwNumber = 0; dwNumber = m_pWaveHdr.dwBytesRecorded; if (waveInUnprepareHeader(hWaveIn, &m_pWaveHdr, sizeof(WAVEHDR))) { PRINT(_T("\r\n Fail: waveInUnprepareHeader")); } else { return 0; } return 1; } VOID ThreadProc1(PVOID pData) { int dwNumber; PRINT(_T("\r\n ThreadProc1 Begin..")); while (iStart) { sample(m_hWnd); dwNumber = m_pWaveHdr.dwBytesRecorded; displayWave(m_hWnd); PRINT(_T(".")); } PRINT(_T("\r\n ThreadProc1 Exit.")); _endthread(); }

 

2022-05-29,今天终于把声音波形给画出来了。原因是:8位及以下采样,声音数据是用无符号数据记录的,应该定义成unsigned char。

 

posted @ 2022-05-27 22:54  XGZ21  阅读(333)  评论(0编辑  收藏  举报