// VoiceRecFFTW5.cpp : Defines the entry point for the application. // #include "framework.h" #include "math.h" #include "fftw3.h" #include "list" #include "VoiceRecFFTW5.h" constexpr auto MAX_LOADSTRING = 100; int M = 24000; // time domain max signal size int MD = 12000; // reduced (filtered) time domain max signal size int N = 2400; // time domain rec. pattern size int ND = 1200; // reduced (filtered) time domain rec. pattern size int K = 600; // rec. time domain scanning buffer size int KX = 900; // rec. DB freq. buffer size int SW = 0; int rez; // selected pattern nr. in DB int nrSample; // counter int nrDbPatternsTotal = 210; // total number of patterns in DB int nrDbPatternsPerVoice = 30; // number of patterns per voice in DB short POM[24000]; // time domain signal buffer char POM1[200], ch; double X[900]; // freq. buffer double R[210][900]; // rec. DB array double S[24000]; // reduced signal buffer double SX[1800], SX1[1800]; // pattern buffer double largest; // max probab. of pattern char voices[10][12] = { "1. A\0", "2. E\0", "3. I\0", "4. O\0", "5. U\0", "6. TA(1)\0", "7. TE(2)\0", "8. TI(3)\0", "9. TO(4)\0", "10. TU(5)\0" }; int selClan; fftw_plan plan; void NormPNN() { int i; double sum; sum = 0; for (i = 0; i < KX; i++) sum += X[i]; if (sum > 0) for (i = 0; i < KX; i++) X[i] /= sum; } void PNN() { int i, j; double sum; rez = -1; largest = 0; for (i = 0; i < nrDbPatternsTotal; i++) { sum = 0; for (j = 0; j < KX; j++) { sum += fabs(X[j] - R[i][j]); } sum = exp(-pow(sum, 8) / 0.0002); if (sum > largest) { largest = sum; rez = i; } } } void ProcessResult() { int rez1; rez1 = rez / nrDbPatternsPerVoice + 1; switch (rez1) { case 0: ch = '$'; break; case 1: ch = 'a'; break; case 2: ch = 'e'; break; case 3: ch = 'i'; break; case 4: ch = 'o'; break; case 5: ch = 'u'; break; case 6: ch = '1'; // "TA" break; case 7: ch = '2'; // "TE" break; case 8: ch = '3'; // "TI" break; case 9: ch = '4'; // "TO" break; case 10: ch = '5'; // "TU" break; } } void FFT(double* x, fftw_complex* y) { int i; fftw_execute(plan); for (i = 0; i < 300; i++) { y[i][0] = fabs((y[i][0]) / 600); } } void Distances(double** G, int* put) { std::list N, path; std::list::iterator n, m, it, it1; int i; for (i = 0; i < 300; ++i) N.push_back(i); n = N.begin(); path.splice(path.end(), N, n); while (!N.empty()) { it1 = N.begin(); it = path.begin(); for (m = path.begin(); m != path.end(); ++m) { for (n = N.begin(); n != N.end(); ++n) { if (G[*n][*m] > G[*it1][*it]) { it = m; it1 = n; } } } path.splice(path.end(), N, it1); } i = 0; for (n = path.begin(); n != path.end(); ++n) put[i++] = *n; } void ReduceSignal(int nrSamp) { int i; double* x = (double*)fftw_malloc(sizeof(double) * nrSamp); for (i = 0; i < nrSamp; i++) x[i] = S[i]; fftw_complex* y = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * ((size_t)(nrSamp / 2) + 1)); fftw_plan plan1 = fftw_plan_dft_r2c_1d(nrSamp, x, y, FFTW_ESTIMATE); fftw_execute(plan1); fftw_plan plan2 = fftw_plan_dft_c2r_1d(nrSamp / 2, y, x, FFTW_ESTIMATE); fftw_execute(plan2); for (i = 0; i < nrSamp / 2; i++) S[i] = x[i] / nrSamp; fftw_free(x); fftw_free(y); fftw_destroy_plan(plan1); fftw_destroy_plan(plan2); } // 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 Create30ElementsDB(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 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_VOICERECFFTW5, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_VOICERECFFTW5)); 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_VOICERECFFTW5)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_VOICERECFFTW5); 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, 900 + 16, 384 + 59, nullptr, nullptr, hInstance, nullptr); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxClient; static int cyClient; int i, j, m; FILE* stream; switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case ID_FILE_LOADDATABASE: { i = MessageBox(hWnd, TEXT("Do You want to load DB ?"), TEXT("VoiceRecFFTW4 -> Message:"), MB_OKCANCEL | MB_ICONQUESTION); if (i == IDCANCEL) { break; } DisableProcessWindowsGhosting(); // ********** load voice recog. DB ********** int mess = 0; SW = 1; for (m = 0; m < nrDbPatternsTotal; m++) { sprintf_s(POM1, 100, ".\\DAT\\%d.dat", m + 1); if ((fopen_s(&stream, POM1, "r+b") == 0) && (stream != NULL)) { fread(R[m], sizeof(double), 900, stream); fclose(stream); } else { mess = -1; MessageBox(hWnd, TEXT("Problem opening the file x.dat !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } } // ********** select freq. pattern to show (TA) ********** for (i = 0; i < 900; i++) X[i] = R[46][i]; InvalidateRect(hWnd, NULL, TRUE); if (mess == 0) MessageBox(hWnd, TEXT("DB succesfully loaded !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); } break; case ID_RECOGNITION_RECOGNIZE: { i = MessageBox(hWnd, TEXT("Do You want to start recognition ?"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OKCANCEL | MB_ICONQUESTION); if (i == IDCANCEL) { break; } DisableProcessWindowsGhosting(); // ********** create dynamic arrays for FFTW ********** double* x = (double*)fftw_malloc(sizeof(double) * 600); fftw_complex* y = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * ((size_t)300 + 1)); plan = fftw_plan_dft_r2c_1d(600, x, y, FFTW_ESTIMATE); // ********** load signal for recognition ********** int mess = 0; SW = 0; if ((fopen_s(&stream, "signal.pcm", "r+b") == 0) && (stream != NULL)) { nrSample = (unsigned int)fread(POM, sizeof(short), (M), stream); fclose(stream); } else { mess = -1; goto LAB2; } if (nrSample < N) { mess = -2; goto LAB2; } // ***** reduce signal 2x with FFTW transform ***** for (i = 0; i < nrSample; i++) S[i] = (double)POM[i]; ReduceSignal(nrSample); // ********** open result file ********** if ((fopen_s(&stream, "result.txt", "w+t") == 0) && (stream != NULL)) { // ********** save some data in the result file ********** fprintf_s(stream, "\n char nr. probab. dbPatternNr. \n"); // ********** recognition loop ********** m = 0; while (m < nrSample / 2 - 1200) { // ********** clear rec. freq. buffer ********** for (i = 0; i < 900; i++) X[i] = 0; for (i = 0; i < 1200; i++) { SX[i] = S[m + i]; } // ********** scan first rec. subpattern ********** j = 0; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 599; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 0; j < 300; j++) X[j] += (y[j][0]); } // ********** scan second rec. subpattern ********** j = 300; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 899; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 300; j < 600; j++) X[j] += (y[j - 300][0]); } // ********** scan third rec. subpattern ********** j = 600; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 1199; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 600; j < 900; j++) X[j] += (y[j - 600][0]); } // ********** normalize, pitch & log ********** double sum = 0; for (i = 0; i < 900; i++) sum += X[i]; sum /= 900; if (sum > 0) for (i = 0; i < 900; i++) X[i] /= sum; for (i = 0; i < 900; i++) X[i] = log(X[i] + 1); // ********** normalize rec. freq. pattern ********** NormPNN(); // ********** find pattern in the rec. DB with max probability ********** PNN(); // ********** find voice (character) for that pattern ********** ProcessResult(); // ********** save rec. pattern data to result.txt file ********** fprintf_s(stream, "\n %c\t%d\t%.5f\t %d\n", ch, m*2, largest, rez + 1); m += 10; } // end while() fclose(stream); } // end if() else { mess = -3; } // ********** destroy dynamic arrays ********** LAB2: fftw_free(x); fftw_free(y); fftw_destroy_plan(plan); fftw_cleanup(); InvalidateRect(hWnd, NULL, TRUE); switch (mess) { case (0): MessageBox(hWnd, TEXT("Recognition succesfully finished !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-1): MessageBox(hWnd, TEXT("(-1) Problem opening the file signal.pcm !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-2): MessageBox(hWnd, TEXT("(-2) Signal too small !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-3): MessageBox(hWnd, TEXT("(-3) Problem opening the file result.txt !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } // end switch() } break; case ID_CREATION_CREATEDATABASE: { i = MessageBox(hWnd, TEXT("Do You want to create DB ?"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OKCANCEL | MB_ICONQUESTION); if (i == IDCANCEL) { break; } DisableProcessWindowsGhosting(); // ********** create dynamic arrays for FFTW ********** double* x = (double*)fftw_malloc(sizeof(double) * 600); fftw_complex* y = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * ((size_t)300 + 1)); plan = fftw_plan_dft_r2c_1d(600, x, y, FFTW_ESTIMATE); // ********** DB creation loop ********** int mess = 0; SW = 0; for (m = 0; m < nrDbPatternsTotal; m++) { // ********** load time domain pattern ********** sprintf_s(POM1, 200, ".\\Baza2400-44K100\\%d.pcm", m + 1); if ((fopen_s(&stream, POM1, "r+b") == 0) && (stream != NULL)) { nrSample = (int)fread(POM, sizeof(short), (M), stream); fclose(stream); } else { mess = -1; MessageBox(hWnd, TEXT("Problem opening the file x.pcm !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } if (nrSample < 2400) { mess = -2; MessageBox(hWnd, TEXT("Signal too small !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } // ***** reduce (filter) time domain rec. pattern ***** for (i = 0; i < 2400; i++) S[i] = (double)POM[i]; ReduceSignal(2400); for (i = 0; i < 1200; i++) SX[i] = S[i]; // ********** clear freq. buffer ********** for (i = 0; i < 900; i++) { X[i] = 0; } // ********** scan first rec. subpattern ********** j = 0; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 599; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 0; j < 300; j++) X[j] += (y[j][0]); } // ********** scan second rec. subpattern ********** j = 300; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 899; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 0; j < 300; j++) X[j + 300] += (y[j][0]); } // ********** scan third rec. subpattern ********** j = 600; for (i = 0; i < 600; i++) { SX1[i] = SX[j++]; } j = 1199; for (i = 600; i < 1200; i++) { SX1[i] = SX[j--]; } j = 0; for (i = 1200; i < 1800; i++) { SX1[i] = SX1[j++]; } for (i = 0; i < 1200; i++) { for (j = 0; j < 600; j++) { x[j] = SX1[i + j]; } FFT(x, y); for (j = 0; j < 300; j++) X[j + 600] += (y[j][0]); } // ********** normalize, pitch & log ********** double sum = 0; for (i = 0; i < 900; i++) sum += X[i]; sum /= 900; if (sum > 0) for (i = 0; i < 900; i++) X[i] /= sum; for (i = 0; i < 900; i++) X[i] = log(X[i] + 1); // ********** normalize freq. pattern ********** NormPNN(); // ********** save normalized freq. pattern ********** sprintf_s(POM1, 200, ".\\DAT\\%d.dat", m + 1); if ((fopen_s(&stream, POM1, "w+b") == 0) && (stream != NULL)) { fwrite(X, sizeof(double), 900, stream); fclose(stream); } else { mess = -3; MessageBox(hWnd, TEXT("Problem opening the file x.dat !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } } // ********** destroy dynamic arrays ********** fftw_free(x); fftw_free(y); fftw_destroy_plan(plan); fftw_cleanup(); InvalidateRect(hWnd, NULL, TRUE); if (mess == 0) MessageBox(hWnd, TEXT("DB succesfully created !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); } break; case ID_CREATION_CREATEREDUCEDDATABASE: { selClan = -1; // ********** select voice ********** DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hWnd, Create30ElementsDB); if (selClan == -1) { break; } DisableProcessWindowsGhosting(); int poz; // ********** create dynamic arrays ********** int* put = new int[300](); double** G = new double* [300]; for (i = 0; i < 300; i++) G[i] = new double[300](); double** X_REC = new double* [300]; for (i = 0; i < 300; i++) { X_REC[i] = new double[900](); } // ********** load recog. DB for selected voice ********** int mess = 0; for (i = 0; i < 300; i++) { sprintf_s(POM1, 200, ".DAT\\%d.dat", selClan * 300 + i + 1); if ((fopen_s(&stream, POM1, "r+b") == 0) && (stream != NULL)) { fread(X_REC[i], sizeof(double), 900, stream); fclose(stream); } else { mess = -1; goto LAB1; } } // *** calculate mutual diferences between elements // *** in the recognition database // *** creation of G array for (i = 0; i < 300; i++) for (j = 0; j < 300; j++) { double sum = 0; for (int n = 0; n < 900; n++) sum += fabs(X_REC[i][n] - X_REC[j][n]); G[i][j] = exp(-pow(sum, 8) / 0.0002); } // ********** arrange elements ********** Distances(G, put); // ********** save 30 elements positions ********** poz = 5; sprintf_s(POM1, 200, "%d.txt", selClan + 1); if ((fopen_s(&stream, POM1, "w+t") == 0) && (stream != NULL)) { for (i = poz; i < 300; i += 10) fprintf_s(stream, "%d\n", put[i] + 1); fclose(stream); } else { mess = -2; goto LAB1; } j = 0; for (i = poz; i < 300; i += 10) { // ********** read element from recog. DB considering position ********** sprintf_s(POM1, 200, ".\\DAT\\%d.dat", selClan * 300 + put[i] + 1); if ((fopen_s(&stream, POM1, "r+b") == 0) && (stream != NULL)) { fread(X, sizeof(double), 900, stream); fclose(stream); } else { mess = -3; goto LAB1; } // ********** save element to reduced DB dir. ********** sprintf_s(POM1, 200, ".\\R_DAT\\%d.dat", selClan * 30 + j + 1); if ((fopen_s(&stream, POM1, "w+b") == 0) && (stream != NULL)) { fwrite(X, sizeof(double), 900, stream); fclose(stream); } else { mess = -4; goto LAB1; } j++; } // ********** destroy dynamic arrays ********** LAB1: delete[] put; for (i = 0; i < 300; i++) { delete[] X_REC[i]; } delete[] X_REC; for (i = 0; i < 300; i++) delete[] G[i]; delete[] G; switch (mess) { case (0): MessageBox(hWnd, TEXT("Member DB elements selected !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-1): MessageBox(hWnd, TEXT("(-1) Selected member DB not loaded !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-2): MessageBox(hWnd, TEXT("(-2) txt file with list of reduced DB members not saved !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-3): MessageBox(hWnd, TEXT("(-3) dat file from DAT dir not loaded !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; case (-4): MessageBox(hWnd, TEXT("(-4) dat file not saved to R_DAT dir !"), TEXT("VoiceRecFFTW5 -> Message:"), MB_OK); break; } } 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); } // end switch() } break; case WM_SIZE: { cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); MoveToEx(hdc, 0, cyClient / 2, NULL); LineTo(hdc, cxClient, cyClient / 2); for (i = 0; i < 900; i++) { MoveToEx(hdc, (int)(cxClient * ((i)) / 900), cyClient / 2, NULL); LineTo(hdc, (int)(cxClient * ((i)) / 900), (int)(cyClient / 2 * (1 - (X[i] * 50)))); } if (SW == 1) { SelectObject(hdc, GetStockObject(OEM_FIXED_FONT)); SetBkColor(hdc, RGB(255, 255, 255)); SetTextColor(hdc, RGB(63, 63, 191)); sprintf_s(POM1, 200, "database Pattern TA"); TextOutA(hdc, 40, cyClient / 2 + 20, POM1, (int)strlen(POM1)); } // TODO: Add any drawing code that uses hdc here... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } INT_PTR CALLBACK Create30ElementsDB(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { // Add items to list. HWND hwndList = GetDlgItem(hDlg, IDC_LIST1); for (int i = 0; i < nrDbPatternsTotal / nrDbPatternsPerVoice; i++) { int pos = (int)SendMessageA(hwndList, LB_ADDSTRING, 0, (LPARAM)voices[i]); SendMessage(hwndList, LB_SETITEMDATA, pos, (LPARAM)i); } selClan = -1; // Set input focus to the list box. SetFocus(hwndList); return TRUE; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: selClan = -1; case IDOK: // destroyWindow("MemberImage"); EndDialog(hDlg, LOWORD(wParam)); return TRUE; case IDC_LIST1: switch (HIWORD(wParam)) { case LBN_SELCHANGE: HWND hwndList = GetDlgItem(hDlg, IDC_LIST1); HWND hwndList1 = GetDlgItem(hDlg, IDC_STATIC); // Get selected index. int lbItem = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0); // Get item data. selClan = (int)SendMessage(hwndList, LB_GETITEMDATA, lbItem, 0); return TRUE; } } return TRUE; } } return FALSE; } // 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; }