#include #include // add winmm.lib to Project -Settings -Link #include // where WAVEFORMATEXTENSIBLE is defined #include // required by KsMedia.h #include // mulitmedia GUID info #include "resource.h" #define WHITE 0xFCFCFC #define TIMER_RESOLUTION 1 #define WM_USER2 WM_USER+1 #define STOPPED 0 #define PLAYING 1 #define PAUSED 2 #define TOPRED 1 #define TOPGREEN 2 #define BOTTOMRED 3 #define BOTTOMGREEN 4 int x, y, z, PTR, BufSize, divisor, zoom, middle, topmiddle, bottommiddle, PointsPerScreen, MillisecondsPerScreen; int playing, lastPTR, linesperscreen = 1, rectrightx2, ratio = 16, xPos = -1; unsigned int uTimerID = 0; DWORD fileSize, fileSize2, dwBytesRead, dwBytesWritten, subchunksize, nextchunk, nSamplesPerSec, Milliseconds, Seconds, Minutes; DWORD X; WORD nChannels, wBitsPerSample; SHORT Short; double pointsPerScreen, pointsPerMillisecond, millisecondsPerScreen, totalMilliseconds, d; char Filename[MAX_PATH]; char FullFilename[MAX_PATH]; char **FilePart; char CmdLine; char szAppName[] = "PlayWave"; BYTE LineToShift; BYTE *WaveBuf, *WaveBuf2; BYTE *Buf; BOOL first = TRUE, nosendtoflg = FALSE, oddeven, topchanged, bottomchanged; char WaveHeight[] = "Vertical Scale = 1:1"; char Left[] = "1"; char Right[] = "1"; char time[] = "00:00:000"; char temp[10]; char Help[] = "\ The middle line shows what's being heard.\n\ The top line is the preceding waveform.\n\ The bottom line is the next waveform.\n\ \n\ SpaceBar to Play or Pause\n\ PgDown for the next screen's waveform\n\ PgUp for the previous screen's waveform\n\ Home or End\n\ Esc to Stop Playing or to Exit if not Playing\n\ \n\ If the WAVE file is stereo, instead of lines,\n\ red and green dots will show for the two channels.\n\ \n\ Press the Left Mouse Button to draw a vertical line.\n\ \n\ Doug Cox\n\ 1 Nov 2010\n\ http://jdmcox.com\n\ jdmcox@jdmcox.com"; HWND hwnd, hwndPhase; HANDLE hFile; HINSTANCE hInst; HMENU hMenu; RECT rect; HBRUSH hBrush; HPEN hPen, hRedPen, hGreenPen; HDC hdc; PAINTSTRUCT ps; OPENFILENAME ofn; WIN32_FIND_DATA fd; HWAVEOUT hWaveOut; WAVEHDR WaveOutHdr; //typedef struct { // WAVEFORMATEX Format; // union { // WORD wValidBitsPerSample; // this is for 24 bit sound // WORD wSamplesPerBlock; // WORD wReserved; // } Samples; // DWORD dwChannelMask; // GUID SubFormat; //} WAVEFORMATEXTENSIBLE; WAVEFORMATEXTENSIBLE WaveFormat; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MSG msg; WNDCLASS wndclass; hInst = hInstance; hBrush = CreateSolidBrush(WHITE); hPen = CreatePen(PS_SOLID, 0, 0); hRedPen = CreatePen(PS_SOLID, 0, 0x0000F0); hGreenPen = CreatePen(PS_SOLID, 0, 0x00F000); wndclass.style = CS_HREDRAW|CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = hBrush; // (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = "MENU"; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) return 0; if (szCmdLine[0] == 0) nosendtoflg = TRUE; else { y = 0; CmdLine = '\x0'; if (szCmdLine[0] == '"') { CmdLine = '"'; y = 1; } for (x = 0; szCmdLine[y] != CmdLine ; x++, y++) Filename[x] = szCmdLine[y]; Filename[x] = 0; GetFullPathName(Filename, MAX_PATH, FullFilename, FilePart); } hwnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOWMAXIMIZED); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void GetTime(void) { _asm fld totalMilliseconds _asm fistp Milliseconds Minutes = Milliseconds / 60000; Seconds = (Milliseconds % 60000) / 1000; time[0] = (char)(Minutes / 10) + '0'; time[1] = (char)(Minutes % 10) + '0'; time[3] = (char)(Seconds / 10) + '0'; time[4] = (char)(Seconds % 10) + '0'; time[6] = (char)((Milliseconds % 1000) / 100) + '0'; time[7] = (char)((Milliseconds % 100) / 10) + '0'; time[8] = (char)(Milliseconds % 10) + '0'; } void StopPlaying(void) { waveOutUnprepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); waveOutReset(hWaveOut); waveOutClose(hWaveOut); if (uTimerID) { timeKillEvent(uTimerID); uTimerID = 0; timeEndPeriod(TIMER_RESOLUTION); } playing = STOPPED; } void ShowRatios(void) { switch (ratio) { case 2: Left[0] = '1'; Right[0] = '8'; break; case 4: Left[0] = '1'; Right[0] = '4'; break; case 8: Left[0] = '1'; Right[0] = '2'; break; case 16: Left[0] = '1'; Right[0] = '1'; break; case 32: Left[0] = '2'; Right[0] = '1'; break; case 64: Left[0] = '4'; Right[0] = '1'; break; case 128: Left[0] = '8'; Right[0] = '1'; break; } } LRESULT CALLBACK GotoProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { static char temp[3]; static HWND hwndEdit1, hwndEdit2, hwndEdit3; switch (message) { case WM_INITDIALOG: hwndEdit1 = GetDlgItem(hwndDlg, IDC_EDIT1); hwndEdit2 = GetDlgItem(hwndDlg, IDC_EDIT2); hwndEdit3 = GetDlgItem(hwndDlg, IDC_EDIT3); SetFocus(hwndEdit1); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (GetWindowText(hwndEdit1, temp, 3)) { if (temp[1]) Minutes = ((temp[0] - '0') * 10) + (temp[1] - '0'); else Minutes = temp[0] - '0'; } else Minutes = 0; if (GetWindowText(hwndEdit2, temp, 3)) { if (temp[1]) Seconds = ((temp[0] - '0') * 10) + (temp[1] - '0'); else Seconds = temp[0] - '0'; } else Seconds = 0; temp[0] = '0'; temp[1] = '0'; temp[2] = '0'; if (GetWindowText(hwndEdit3, temp, 4)) { Milliseconds = ((temp[0] - '0') * 100) + ((temp[1] - '0') * 10) + (temp[2] - '0'); } else Milliseconds = 0; EndDialog (hwndDlg, TRUE); return TRUE; case IDCANCEL: EndDialog (hwndDlg, FALSE); return FALSE; } } return 0; } int CALLBACK PhaseProc(HWND hwndPhase, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: LineToShift = 0; break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_RADIO1: CheckRadioButton(hwndPhase, IDC_RADIO1, IDC_RADIO4, IDC_RADIO1); LineToShift = TOPRED; break; case IDC_RADIO2: CheckRadioButton(hwndPhase, IDC_RADIO1, IDC_RADIO4, IDC_RADIO2); LineToShift = TOPGREEN; break; case IDC_RADIO3: CheckRadioButton(hwndPhase, IDC_RADIO1, IDC_RADIO4, IDC_RADIO3); LineToShift = BOTTOMRED; break; case IDC_RADIO4: CheckRadioButton(hwndPhase, IDC_RADIO1, IDC_RADIO4, IDC_RADIO4); LineToShift = BOTTOMGREEN; break; } break; case WM_CLOSE: LineToShift = 0; DestroyWindow(hwndPhase); hwndPhase = NULL; break; } return 0; } void CALLBACK TimerFunc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { PostMessage(hwnd, WM_USER2, 0, 0); } void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT message, DWORD dwInstance, DWORD wParam, DWORD lParam) { if (message == WOM_DONE) PostMessage(hwnd, WM_USER, 0, 0); } void OpenWaveFile(void) { hFile = CreateFile(FullFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { if (fileSize = GetFileSize(hFile, NULL)) { PTR = 0; divisor = 0x10000; ratio = 16; totalMilliseconds = 0.0; WaveHeight[17] = Left[0]; WaveHeight[19] = Right[0]; time[0] = '0'; time[1] = '0'; time[3] = '0'; time[4] = '0'; time[6] = '0'; time[7] = '0'; time[8] = '0'; if (WaveBuf) VirtualFree(WaveBuf, 0, MEM_RELEASE); WaveBuf = VirtualAlloc(NULL, fileSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); ReadFile(hFile, WaveBuf, fileSize, &dwBytesRead, NULL); CloseHandle(hFile); topchanged = bottomchanged = FALSE; if (*(DWORD*)&WaveBuf[8] == 0x45564157) {// "WAVE" subchunksize = *(DWORD*)&WaveBuf[16]; nextchunk = subchunksize + 20; if (*(DWORD*)&WaveBuf[nextchunk] == 0x74636166)// "fact" nextchunk += 12; if (*(DWORD*)&WaveBuf[nextchunk] != 0x61746164) // "data" nextchunk += (*(DWORD*)&WaveBuf[nextchunk+4]) + 8; if (*(DWORD*)&WaveBuf[nextchunk] == 0x61746164) {// "data" Buf = &WaveBuf[nextchunk+8]; // beginning of data BufSize = *(int*)&WaveBuf[nextchunk+4]; WaveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; WaveFormat.Format.nChannels = *(WORD*)&WaveBuf[22]; WaveFormat.Format.nSamplesPerSec = *(DWORD*)&WaveBuf[24]; WaveFormat.Format.nAvgBytesPerSec = *(DWORD*)&WaveBuf[28]; // byte rate WaveFormat.Format.nBlockAlign = *(WORD*)&WaveBuf[32]; WaveFormat.Format.wBitsPerSample = *(WORD*)&WaveBuf[34]; WaveFormat.Format.cbSize = 22; WaveFormat.Samples.wValidBitsPerSample = WaveFormat.Format.wBitsPerSample; WaveFormat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; // the following should be WaveFormat.Subformat = KSDATAFORMAT_SUBTYPE_PCM defined as 00000001-0000-0010-8000-00aa00389b71 (but that doesn't work here) WaveFormat.SubFormat.Data1 = 1; WaveFormat.SubFormat.Data2 = 0; WaveFormat.SubFormat.Data3 = 0x10; WaveFormat.SubFormat.Data4[0] = 0x80; WaveFormat.SubFormat.Data4[1] = 0; WaveFormat.SubFormat.Data4[2] = 0; WaveFormat.SubFormat.Data4[3] = 0xAA; WaveFormat.SubFormat.Data4[4] = 0; WaveFormat.SubFormat.Data4[5] = 0x38; WaveFormat.SubFormat.Data4[6] = 0x9B; WaveFormat.SubFormat.Data4[7] = 0x71; nChannels = WaveFormat.Format.nChannels; nSamplesPerSec = WaveFormat.Format.nSamplesPerSec; wBitsPerSample = WaveFormat.Format.wBitsPerSample; pointsPerMillisecond = (double)nSamplesPerSec / 1000.0; millisecondsPerScreen = pointsPerScreen / pointsPerMillisecond; waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFormat.Format, (DWORD)&waveOutProc, 0, CALLBACK_FUNCTION); WaveOutHdr.lpData = (LPSTR)&WaveBuf[nextchunk+8]; WaveOutHdr.dwBufferLength = *(DWORD*)&WaveBuf[nextchunk+4]; lastPTR = WaveOutHdr.dwBufferLength - rect.right; WaveOutHdr.dwBytesRecorded = 0; WaveOutHdr.dwUser = 0; WaveOutHdr.dwFlags = 0; WaveOutHdr.dwLoops = 0; waveOutPrepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); x = waveOutWrite(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); timeBeginPeriod(TIMER_RESOLUTION); uTimerID = timeSetEvent(100, TIMER_RESOLUTION, TimerFunc, 0, TIME_PERIODIC);// every 100 milliseconds playing = PLAYING; InvalidateRect(hwnd, &rect, FALSE); for (x = 0; Filename[x] != 0; x++) ; Filename[x++] = ' '; _itoa(WaveFormat.Format.nSamplesPerSec, temp, 10); for (y = 0; temp[y] != 0; x++, y++) Filename[x] = temp[y]; Filename[x++] = 'H'; Filename[x++] = 'z'; Filename[x++] = ' '; _itoa(WaveFormat.Format.wBitsPerSample, temp, 10); for (y = 0; temp[y] != 0; x++, y++) Filename[x] = temp[y]; Filename[x++] = 'b'; Filename[x++] = 'i'; Filename[x++] = 't'; Filename[x] = 0; SetWindowText(hwnd, Filename); // 11025Hz 16bit } else { VirtualFree(WaveBuf, 0, MEM_RELEASE); WaveBuf = NULL; MessageBox(hwnd, "", ERROR, MB_OK); } } else { VirtualFree(WaveBuf, 0, MEM_RELEASE); WaveBuf = NULL; MessageBox(hwnd, "That's not a WAVE file", ERROR, MB_OK); } } } } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: //asdf //dHz = 1200.0; //weight = (dHz - 20.0) / 20000.0; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = hInst; ofn.lpstrFilter = " WAVE files\0""*.wav;*.wave\0\0"; ofn.lpstrFile = FullFilename; ofn.lpstrFileTitle = Filename; ofn.Flags = OFN_HIDEREADONLY|OFN_NOCHANGEDIR|OFN_ENABLESIZING; ofn.lpstrTitle = NULL; ofn.lpstrDefExt = "wav"; ofn.nMaxFile = MAX_PATH; ofn.lpstrCustomFilter = 0; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lCustData = 0; ofn.lpfnHook = NULL; ofn.lpTemplateName = NULL; hMenu = GetMenu(hwnd); WaveBuf = NULL; WaveBuf2 = NULL; playing = STOPPED; return 0; case WM_SIZE: rect.left = rect.top = 0; rect.right = LOWORD(lParam); rectrightx2 = rect.right * 2; rect.bottom = HIWORD(lParam); middle = rect.bottom / 2; topmiddle = rect.bottom / 4; bottommiddle = rect.bottom * 3 / 4; PointsPerScreen = rect.right; _asm fild PointsPerScreen _asm fstp pointsPerScreen return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case ID_FILES_OPEN: if (GetOpenFileName(&ofn)) OpenWaveFile(); break; case ID_FILES_EXIT: DestroyWindow(hwnd); break; case ID_PLAY: if (playing != PLAYING) { if (PTR < (BufSize - rectrightx2)) { if (playing == STOPPED) { waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFormat.Format, (DWORD)&waveOutProc, 0, CALLBACK_FUNCTION); WaveOutHdr.lpData = (LPSTR)&Buf[PTR]; WaveOutHdr.dwBufferLength = *(DWORD*)&WaveBuf[nextchunk+4]; WaveOutHdr.dwBufferLength -= PTR; WaveOutHdr.dwBytesRecorded = 0; WaveOutHdr.dwUser = 0; WaveOutHdr.dwFlags = 0; WaveOutHdr.dwLoops = 0; waveOutPrepareHeader(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &WaveOutHdr, sizeof(WAVEHDR)); } else if (playing == PAUSED) { waveOutRestart(hWaveOut); } timeBeginPeriod(TIMER_RESOLUTION); uTimerID = timeSetEvent(100, TIMER_RESOLUTION, TimerFunc, 0, TIME_PERIODIC); playing = PLAYING; InvalidateRect(hwnd, &rect, FALSE); } } break; case ID_PAUSE: if (playing == PLAYING) { waveOutPause(hWaveOut); if (uTimerID) { timeKillEvent(uTimerID); uTimerID = 0; timeEndPeriod(TIMER_RESOLUTION); } playing = PAUSED; InvalidateRect(hwnd, &rect, FALSE); } break; case ID_STOP: if (playing != STOPPED) { StopPlaying(); SendMessage(hwnd, WM_KEYDOWN, VK_HOME, 0); } break; case ID_PHASESHIFT: hwndPhase = CreateDialog(hInst, "PHASESHIFT", hwnd, PhaseProc); break; case ID_GOTO: if (Filename[0]) { if (DialogBox(hInst, "GOTO", hwnd, GotoProc)) { x = nSamplesPerSec * 2 * ((Minutes * 60) + Seconds); d = pointsPerMillisecond * 2.0 * (double)(Milliseconds + (((Minutes * 60) + Seconds) * 1000)); x = (int)d & 0xFFFFFFFE; // to make it an even number (data is in WORDS) x &= 0xFFFFFFFE; if (x < (BufSize - rectrightx2)) { PTR = x; StopPlaying(); time[0] = (char)(Minutes / 10) + '0'; time[1] = (char)(Minutes % 10) + '0'; time[3] = (char)(Seconds / 10) + '0'; time[4] = (char)(Seconds % 10) + '0'; time[6] = (char)((Milliseconds % 1000) / 100) + '0'; time[7] = (char)((Milliseconds % 100) / 10) + '0'; time[8] = (char)(Milliseconds % 10) + '0'; InvalidateRect(hwnd, &rect, FALSE); } } } break; case ID_LINESSCREEN_1: linesperscreen = 1; CheckMenuItem(hMenu, ID_LINESSCREEN_1, MF_BYCOMMAND|MF_CHECKED); CheckMenuItem(hMenu, ID_LINESSCREEN_3, MF_BYCOMMAND|MF_UNCHECKED); InvalidateRect(hwnd, &rect, FALSE); break; case ID_LINESSCREEN_3: linesperscreen = 3; CheckMenuItem(hMenu, ID_LINESSCREEN_3, MF_BYCOMMAND|MF_CHECKED); CheckMenuItem(hMenu, ID_LINESSCREEN_1, MF_BYCOMMAND|MF_UNCHECKED); InvalidateRect(hwnd, &rect, FALSE); break; case MY_HELP: MessageBox(hwnd, Help, szAppName, MB_OK); break; case PLUS: if (ratio < 128) { divisor >>= 1; ratio <<= 1; ShowRatios(); WaveHeight[17] = Left[0]; WaveHeight[19] = Right[0]; InvalidateRect(hwnd, &rect, FALSE); } break; case MINUS: if (ratio > 2) { divisor <<= 1; ratio >>= 1; ShowRatios(); WaveHeight[17] = Left[0]; WaveHeight[19] = Right[0]; InvalidateRect(hwnd, &rect, FALSE); } break; } return 0; case WM_LBUTTONDOWN: xPos = LOWORD(lParam); if (playing != PLAYING) InvalidateRect(hwnd, &rect, FALSE); return 0; case WM_KEYDOWN: switch (wParam) { case VK_SPACE: if (playing == PLAYING) SendMessage(hwnd, WM_COMMAND, ID_PAUSE, 0); else if (Filename[0]) SendMessage(hwnd, WM_COMMAND, ID_PLAY, 0); InvalidateRect(hwnd, &rect, FALSE); break; case VK_NEXT: if (playing != PLAYING) { if (PTR < (BufSize - rectrightx2)) { PTR += rectrightx2; totalMilliseconds += millisecondsPerScreen; GetTime(); if (playing == PAUSED) StopPlaying(); InvalidateRect(hwnd, &rect, FALSE); } } break; case VK_PRIOR: if (playing != PLAYING) { // if (PTR < (int)(nextchunk+8+rect.right)) { // PTR = rect.right; // totalMilliseconds = millisecondsPerScreen; // InvalidateRect(hwnd, &rect, FALSE); // } if (PTR >= rectrightx2) { PTR -= rectrightx2; totalMilliseconds -= millisecondsPerScreen; GetTime(); if (playing == PAUSED) StopPlaying(); InvalidateRect(hwnd, &rect, FALSE); UpdateWindow(hwnd); } } break; case VK_HOME: if (playing != PLAYING) { PTR = 0; totalMilliseconds = 0.0; time[0] = '0'; time[1] = '0'; time[3] = '0'; time[4] = '0'; time[6] = '0'; time[7] = '0'; time[8] = '0'; playing = STOPPED; InvalidateRect(hwnd, &rect, FALSE); } break; case VK_END: if (playing != PLAYING) { PTR = BufSize - rectrightx2; totalMilliseconds = PTR / (pointsPerMillisecond * 2); GetTime(); InvalidateRect(hwnd, &rect, FALSE); } break; case VK_ESCAPE: if (playing == PLAYING) SendMessage(hwnd, WM_COMMAND, ID_STOP, 0); else DestroyWindow(hwnd); break; case 187:// '+' SendMessage(hwnd, WM_COMMAND, PLUS, 0); break; case 189:// '-' SendMessage(hwnd, WM_COMMAND, MINUS, 0); break; } return 0; case WM_USER2:// "00:00:000" time[6]++; if (time[6] == ':') { time[6] = '0'; time[4]++; if (time[4] == ':') { time[4] = '0'; time[3]++; if (time[3] == '6') { time[3] = '0'; time[1]++; if (time[1] == ':') { time[1] = '0'; time[0]++; } } } } PTR += (nSamplesPerSec / 5) & 0xFFFFFFFE; // to make it even if ((PTR < lastPTR) && (PTR < (BufSize - rectrightx2))) { totalMilliseconds += 100; InvalidateRect(hwnd, &rect, FALSE); } else PTR -= (nSamplesPerSec / 5) & 0xFFFFFFFE; // to make it even return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); oddeven = 1; FillRect(hdc, &rect, hBrush); if (linesperscreen == 3) { MoveToEx(hdc, 0, topmiddle, NULL); LineTo(hdc, rect.right, topmiddle); } MoveToEx(hdc, 0, middle, NULL); LineTo(hdc, rect.right, middle); if (linesperscreen == 3) { MoveToEx(hdc, 0, bottommiddle, NULL); LineTo(hdc, rect.right, bottommiddle); } if (WaveBuf) { SetBkMode(hdc, TRANSPARENT); TextOut(hdc, 0, middle - 20, WaveHeight, 20); TextOut(hdc, 0, middle + 10, time, 9); SetBkMode(hdc, OPAQUE); if (WaveFormat.Format.nChannels == 1) { if ((linesperscreen == 3) && (PTR >= rectrightx2) && (PTR < (BufSize - rectrightx2))) { MoveToEx(hdc, 0, topmiddle, NULL); for (x = 0, y = 0; x < rect.right; x++, y += 2) { LineTo(hdc, x, topmiddle - (*(SHORT*)&Buf[y+PTR-rectrightx2]*rect.bottom/divisor)); } } if (PTR < (BufSize - rectrightx2)) { MoveToEx(hdc, 0, middle, NULL); for (x = 0, y = 0; x < rect.right; x++, y += 2) { LineTo(hdc, x, middle - (*(SHORT*)&Buf[y+PTR]*rect.bottom/divisor)); } } if ((linesperscreen == 3) && (PTR < (BufSize - (rect.right*4)))) { MoveToEx(hdc, 0, bottommiddle, NULL); for (x = 0, y = 0; x < rect.right; x++, y += 2) { LineTo(hdc, x, bottommiddle - (*(SHORT*)&Buf[y+PTR+rectrightx2]*rect.bottom/divisor)); } } } else { // stereo for (x = 0, z = 0; x < rect.right; x++, z += 2) { if (oddeven) SelectObject(hdc, hRedPen); // first entry in Buf is red else SelectObject(hdc, hGreenPen); // second is green oddeven ^= 1; y = middle - *(SHORT*)&Buf[z+PTR]*rect.bottom/divisor; Ellipse(hdc, x-2, y-2, x+2, y+2); } } } SelectObject(hdc, hPen); if (xPos != -1) { MoveToEx(hdc, xPos, 0, NULL); LineTo(hdc, xPos, rect.bottom); } // xPos = -1; EndPaint(hwnd, &ps); if (first) { first = FALSE; if (nosendtoflg) GetOpenFileName (&ofn); OpenWaveFile(); } return 0; case WM_USER: StopPlaying(); return 0; case WM_DESTROY: if (topchanged) { hFile = CreateFile("Top.wav", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { WriteFile(hFile, WaveBuf, fileSize, &dwBytesWritten, NULL); CloseHandle(hFile); } } if (bottomchanged) { hFile = CreateFile("Bottom.wav", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { WriteFile(hFile, WaveBuf2, fileSize2, &dwBytesWritten, NULL); CloseHandle(hFile); } } if (WaveBuf != NULL) VirtualFree(WaveBuf, 0, MEM_RELEASE); if (WaveBuf2 != NULL) VirtualFree(WaveBuf2, 0, MEM_RELEASE); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }