#include <Windows.h>
#include <commdlg.h>
#include <stdio.h>
#include "resource.h"
#define WM_STOP (WM_USER+2)
HWND hLog;
void ClearLogBox() {
SetWindowTextW(hLog, L"");
}
void AddLogBox(LPCWSTR lpStr) {
DWORD Len = lstrlenW(lpStr);
DWORD Size = Len + GetWindowTextLengthW(hLog) + 1;
LPWSTR lpNewStr = (LPWSTR)malloc(Size * sizeof(WCHAR));
GetWindowTextW(hLog, lpNewStr, Size);
lstrcatW(lpNewStr, lpStr);
SetWindowTextW(hLog, lpNewStr);
free(lpNewStr);
}
BOOL HaveName;
WCHAR FileName[MAX_PATH], FileTitle[MAX_PATH];
void LoadFile(HWND hDlg) {
OPENFILENAMEW ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.lpstrFilter = L"Wave Files (*.WAV)\0*.wav\0\0";
ofn.lpstrFile = FileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = FileTitle;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrDefExt = L"wav";
if (GetOpenFileNameW(&ofn)) {
AddLogBox(L"Get File \"");
AddLogBox(FileTitle);
AddLogBox(L"\"\r\n");
HaveName = TRUE;
}
}
DWORD GetEditNumber(HWND hEdit) {
DWORD Size = GetWindowTextLengthW(hEdit) + 1;
if (Size == 1) {
return -1;
}
LPWSTR lpBuffer = (LPWSTR)malloc(Size * sizeof(WCHAR));
GetWindowText(hEdit, lpBuffer, Size);
DWORD Ans;
swscanf_s(lpBuffer, L"%u", &Ans);
free(lpBuffer);
return Ans;
}
BOOL Readed;
WAVEFORMATEX WaveFormat;
BYTE* Buffer;
BOOL ReadWave() {
if (Readed) {
free(Buffer);
Buffer = NULL;
Readed = FALSE;
}
HANDLE hFile = CreateFileW(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
AddLogBox(L"Open File Failed\r\n");
return FALSE;
}
DWORD Read = 0, Flag;
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
if (memcmp(&Flag, "RIFF", 4)) {
AddLogBox(L"File Format Mismatch1\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
DWORD t = GetFileSize(hFile, NULL);
if (Flag + 8 != GetFileSize(hFile, NULL)) {
AddLogBox(L"File Format Mismatch2\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
if (memcmp(&Flag, "WAVE", 4)) {
AddLogBox(L"File Format Mismatch3\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
if (memcmp(&Flag, "fmt ", 4)) {
AddLogBox(L"File Format Mismatch4\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
if (Flag != sizeof(WaveFormat)) {
if (Flag == sizeof(PCMWAVEFORMAT)) {
PCMWAVEFORMAT pwm;
if (!ReadFile(hFile, &pwm, sizeof(pwm), &Read, NULL) || Read != sizeof(pwm)) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
memcpy(&WaveFormat, &pwm, sizeof(pwm));
WaveFormat.cbSize = 0;
}
else {
AddLogBox(L"File Format Mismatch5\r\n");
CloseHandle(hFile);
return FALSE;
}
}
else {
if (!ReadFile(hFile, &WaveFormat, sizeof(WaveFormat), &Read, NULL) || Read != sizeof(WaveFormat)) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
}
if (WaveFormat.wFormatTag != 1) {
AddLogBox(L"File Format Mismatch6\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
if (memcmp(&Flag, "data", 4)) {
AddLogBox(L"File Format Mismatch7\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, &Flag, 4, &Read, NULL) || Read != 4) {
AddLogBox(L"Read File Failed\r\n");
CloseHandle(hFile);
return FALSE;
}
Buffer = (BYTE*)malloc(Flag);
if (!Buffer) {
AddLogBox(L"Memory Allocate Fail\r\n");
CloseHandle(hFile);
return FALSE;
}
if (!ReadFile(hFile, Buffer, Flag, &Read, NULL) || Read != Flag) {
AddLogBox(L"Read File Failed\r\n");
free(Buffer);
CloseHandle(hFile);
return FALSE;
}
AddLogBox(L"Success!\r\n");
CloseHandle(hFile);
Readed = TRUE;
return TRUE;
}
HWAVEOUT hWaveOut;
BOOL Play;
WAVEHDR Header1, Header2, Header3;
BYTE* EnterBuffer;
BYTE* LoopBuffer;
CONST LPARAM pHeader1 = (LPARAM)&Header1;
CONST LPARAM pHeader2 = (LPARAM)&Header2;
CONST LPARAM pHeader3 = (LPARAM)&Header3;
void PlayWave(HWND hDlg, DWORD StartLoop, DWORD EndLoop) {
WORD bps = WaveFormat.wBitsPerSample*WaveFormat.nChannels / 8;
EnterBuffer = Buffer;
LoopBuffer = Buffer + StartLoop*bps;
if (MMSYSERR_NOERROR != waveOutOpen(&hWaveOut, WAVE_MAPPER, &WaveFormat, (DWORD)hDlg, 0, CALLBACK_WINDOW)) {
AddLogBox(L"Open Waveout Device Fail\r\n");
return;
}
Header1.lpData = (LPSTR)EnterBuffer;
Header1.dwBufferLength = StartLoop*bps;
Header1.dwLoops = 1;
waveOutPrepareHeader(hWaveOut, &Header1, sizeof(WAVEHDR));
Header2.lpData = (LPSTR)LoopBuffer;
Header2.dwBufferLength = (EndLoop-StartLoop)*bps;
Header2.dwLoops = 1;
waveOutPrepareHeader(hWaveOut, &Header2, sizeof(WAVEHDR));
Header3.lpData = (LPSTR)LoopBuffer;
Header3.dwBufferLength = (EndLoop - StartLoop)*bps;
Header3.dwLoops = 1;
waveOutPrepareHeader(hWaveOut, &Header3, sizeof(WAVEHDR));
Play = TRUE;
}
void ReleaseWave() {
Play = FALSE;
waveOutReset(hWaveOut);
}
BOOL CALLBACK MainProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
hLog = GetDlgItem(hDlg, IDC_EDIT_LOG);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_PLAY), FALSE);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_BUTTON_OPEN:
LoadFile(hDlg);
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_PLAY), HaveName);
return TRUE;
case IDC_BUTTON_PLAY:
if (!Play) {
if (!ReadWave()) {
return TRUE;
}
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_OPEN), FALSE);
PlayWave(hDlg, GetEditNumber(GetDlgItem(hDlg, IDC_EDIT_START)), GetEditNumber(GetDlgItem(hDlg, IDC_EDIT_END)));
}
else {
SendMessageW(hDlg, WM_STOP, 0, 0);
}
return TRUE;
case IDC_BUTTON_CLEAR:
ClearLogBox();
return TRUE;
case IDC_BUTTON_EXIT:
case IDCANCEL:
if (Play) {
SendMessageW(hDlg, WM_STOP, 0, 0);
}
if (HaveName) {
free(Buffer);
}
EndDialog(hDlg, 0);
return TRUE;
}
return FALSE;
case WM_STOP:
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_OPEN), TRUE);
ReleaseWave();
return TRUE;
case MM_WOM_OPEN:
SetWindowTextW(GetDlgItem(hDlg, IDC_BUTTON_PLAY), L"Stop");
waveOutWrite(hWaveOut, &Header1, sizeof(Header1));
waveOutWrite(hWaveOut, &Header2, sizeof(Header2));
waveOutWrite(hWaveOut, &Header3, sizeof(Header3));
return TRUE;
case MM_WOM_DONE:
if (!Play) {
waveOutClose(hWaveOut);
return TRUE;
}
if (lParam == pHeader1) {
AddLogBox(L"Start Loop\r\n");
return TRUE;
}
AddLogBox(L"Loop\r\n");
waveOutWrite(hWaveOut, (PWAVEHDR)lParam, sizeof(WAVEHDR));
return TRUE;
case MM_WOM_CLOSE:
waveOutUnprepareHeader(hWaveOut, &Header1, sizeof(WAVEHDR));
waveOutUnprepareHeader(hWaveOut, &Header2, sizeof(WAVEHDR));
waveOutUnprepareHeader(hWaveOut, &Header3, sizeof(WAVEHDR));
SetWindowTextW(GetDlgItem(hDlg, IDC_BUTTON_PLAY), L"Play");
return TRUE;
}
return FALSE;
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd) {
return DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_MAIN), NULL, MainProc);
}