/* PROJECT: ReactOS sndrec32 * LICENSE: GPL - See COPYING in the top level directory * FILE: base/applications/sndrec32/sndrec32.cpp * PURPOSE: Sound recording * PROGRAMMERS: Marco Pagliaricci (irc: rendar) * Robert Naumann (gonzoMD) */ #include "stdafx.h" #include #include #include #include "sndrec32.h" #include "shellapi.h" #ifndef _UNICODE #define gprintf _snprintf #else #define gprintf _snwprintf #endif HINSTANCE hInst; TCHAR szTitle[MAX_LOADSTRING]; TCHAR szWindowClass[MAX_LOADSTRING]; ATOM MyRegisterClass(HINSTANCE hInstance); ATOM MyRegisterClass_wave(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); BOOL InitInstance_wave(HWND, HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WndProc_wave(HWND, UINT, WPARAM, LPARAM); BOOL win_first, wout_first; HWND main_win; HWND wave_win; HWND slider; HWND buttons[5]; HBITMAP butbmps[5]; HBITMAP butbmps_dis[5]; WNDPROC buttons_std_proc; BOOL butdisabled[5]; BOOL stopped_flag; BOOL isnew; BOOL display_dur; DWORD slider_pos; WORD slider_min; WORD slider_max; DWORD samples_max; OPENFILENAME ofn; TCHAR file_path[MAX_PATH]; TCHAR str_pos[MAX_LOADSTRING]; TCHAR str_dur[MAX_LOADSTRING]; TCHAR str_buf[MAX_LOADSTRING]; TCHAR str_fmt[MAX_LOADSTRING]; TCHAR str_chan[MAX_LOADSTRING]; TCHAR str_mono[10]; TCHAR str_stereo[10]; BOOL path_set; snd::audio_membuffer *AUD_BUF; snd::audio_waveout *AUD_OUT; snd::audio_wavein *AUD_IN; BOOL s_recording; NONCLIENTMETRICS s_info; RECT text_rect; RECT text2_rect; RECT cli; int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); MSG msg; HACCEL hAccelTable; s_info.cbSize = sizeof( NONCLIENTMETRICS ); InitCommonControls(); switch (GetUserDefaultUILanguage()) { case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): SetProcessDefaultLayout(LAYOUT_RTL); break; default: break; } win_first = wout_first = FALSE; text_rect.left = REFRESHA_X; text_rect.top = REFRESHA_Y; text_rect.right = REFRESHA_CX; text_rect.bottom = REFRESHA_CY; text2_rect.left = REFRESHB_X; text2_rect.top = REFRESHB_Y; text2_rect.right = REFRESHB_CX; text2_rect.bottom = REFRESHB_CY; /* Retrieving default system font, and others system informations */ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &s_info, 0); /* Set font size */ s_info.lfMenuFont.lfHeight = 14; /* Inits buttons bitmaps */ butbmps[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START)); butbmps[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END)); butbmps[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY)); butbmps[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP)); butbmps[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC)); butbmps_dis[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START_DIS)); butbmps_dis[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END_DIS)); butbmps_dis[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY_DIS)); butbmps_dis[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP_DIS)); butbmps_dis[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC_DIS)); /* Inits audio devices and buffers */ snd::audio_membuffer AUD_buffer(snd::A44100_16BIT_STEREO); snd::audio_waveout AUD_waveout(snd::A44100_16BIT_STEREO, AUD_buffer); snd::audio_wavein AUD_wavein(snd::A44100_16BIT_STEREO, AUD_buffer); AUD_buffer.play_finished = l_play_finished; AUD_buffer.audio_arrival = l_audio_arrival; AUD_buffer.buffer_resized = l_buffer_resized; AUD_buffer.alloc_seconds(INITIAL_BUFREC_SECONDS); AUD_IN = &AUD_wavein; AUD_OUT = &AUD_waveout; AUD_BUF = &AUD_buffer; /* Inits slider default parameters */ slider_pos = 0; slider_min = 0; slider_max = SLIDER_W; stopped_flag = FALSE; path_set = FALSE; isnew = TRUE; display_dur = TRUE; samples_max = AUD_buffer.total_samples(); s_recording = false; /* Inits strings */ LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING); LoadString(hInstance, IDS_STRPOS, str_pos, MAX_LOADSTRING); LoadString(hInstance, IDS_STRDUR, str_dur, MAX_LOADSTRING); LoadString(hInstance, IDS_STRBUF, str_buf, MAX_LOADSTRING); LoadString(hInstance, IDS_STRFMT, str_fmt, MAX_LOADSTRING); LoadString(hInstance, IDS_STRCHAN, str_chan, MAX_LOADSTRING); LoadString(hInstance, IDS_STRMONO, str_mono, 10); LoadString(hInstance, IDS_STRSTEREO, str_stereo, 10); /* Registers sndrec32 window class */ MyRegisterClass(hInstance); MyRegisterClass_wave(hInstance); if (!InitInstance(hInstance, nCmdShow)) { MessageBox(0, TEXT("CreateWindow() Error!"), TEXT("ERROR"), MB_ICONERROR); return FALSE; } /* Loads key accelerators */ hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_REACTOS_SNDREC32)); /* Starts main loop */ while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(main_win, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } if (wout_first) { AUD_waveout.close(); } if (win_first) { AUD_wavein.close(); } AUD_buffer.clear(); return (int)msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX 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_SNDREC32)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SNDREC32)); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, MAINWINDOW_W, MAINWINDOW_H, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); main_win = hWnd; return TRUE; } ATOM MyRegisterClass_wave(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc_wave; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = 0; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.lpszMenuName = 0; wcex.lpszClassName = TEXT("sndrec32_wave"); wcex.hIconSm = 0; return RegisterClassEx(&wcex); } BOOL InitInstance_wave(HWND f, HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; hWnd = CreateWindowEx(WS_EX_STATICEDGE, TEXT("sndrec32_wave"), TEXT(""), WS_VISIBLE | WS_CHILD, WAVEBAR_X, WAVEBAR_Y, WAVEBAR_CX, WAVEBAR_CY, f, (HMENU)8, hInstance, 0); if (!hWnd ) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); wave_win = hWnd; return TRUE; } LRESULT CALLBACK WndProc_wave(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; HPEN pen; HPEN oldpen; unsigned int max_h = (cli.bottom / 2); unsigned int samples; unsigned int x, line_h; switch (message) { case WM_CREATE: GetClientRect(hWnd, &cli); break; case WM_PAINT: /* Initialize hdc objects */ hdc = BeginPaint(hWnd, &ps); pen = (HPEN)CreatePen(PS_SOLID, 1, WAVEBAR_COLOR); oldpen = (HPEN) SelectObject(hdc, (HBRUSH)pen); if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) { samples = AUD_OUT->tot_samples_buf(); for (unsigned int i = 0; i < WAVEBAR_CX; ++i) { x = (i * samples) / WAVEBAR_CX; line_h = (AUD_OUT->nsample(x) * max_h) / AUD_OUT->samplevalue_max(); if (line_h) { MoveToEx(hdc, i, max_h, 0); LineTo(hdc, i, max_h - (line_h * 2)); LineTo(hdc, i, max_h + (line_h * 2)); } else { SetPixel(hdc, i, max_h, WAVEBAR_COLOR); } } } else if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) { samples = AUD_IN->tot_samples_buf(); for (unsigned int i = 0; i < WAVEBAR_CX; ++i) { x = (i * samples) / WAVEBAR_CX; line_h = (AUD_IN->nsample(x) * max_h) / AUD_IN->samplevalue_max(); if (line_h) { MoveToEx(hdc, i, max_h, 0); LineTo(hdc, i, max_h - (line_h * 2)); LineTo(hdc, i, max_h + (line_h * 2)); } else { SetPixel( hdc, i, max_h, WAVEBAR_COLOR ); } } } else { /* In standby mode draw a simple line */ MoveToEx(hdc, 0, cli.bottom / 2, 0); LineTo(hdc, WAVEBAR_CX, cli.bottom / 2); } SelectObject(hdc, oldpen); DeleteObject( pen ); EndPaint( hWnd, &ps ); break; case WM_USER: break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId; TCHAR str_tmp[MAX_LOADSTRING]; PAINTSTRUCT ps; HDC hdc; HFONT font; HFONT oldfont; long long slid_samp = 0; WCHAR szAppName[100]; HICON hIcon; /* Checking for global pointers to buffer and io audio devices */ if ((!AUD_IN) || (!AUD_OUT) || (!AUD_BUF)) { MessageBox(0, TEXT("Buffer Error"), 0, 0); return 1; } switch (message) { case WM_CREATE: /* Creating the wave bar */ if (!InitInstance_wave(hWnd, hInst, SW_SHOWNORMAL)) { MessageBox(0, TEXT("InitInstance_wave() Error!"), TEXT("ERROR"), MB_ICONERROR); return FALSE; } /* Creating ALL the buttons */ for (int i = 0; i < 5; ++i) { buttons[i] = CreateWindow(TEXT("button"), TEXT(""), WS_CHILD | WS_VISIBLE | BS_BITMAP, BUTTONS_CX + (i * (BUTTONS_W + ((i == 0) ? 0 : BUTTONS_SPACE))), BUTTONS_CY, BUTTONS_W, BUTTONS_H, hWnd, (HMENU)UlongToPtr(i), hInst, 0); if (!buttons[i]) { MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0); return FALSE; } /* Realize the button bmp image */ SendMessage(buttons[i], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[i]); UpdateWindow(buttons[i]); disable_but(i); } /* Creating the SLIDER window */ slider = CreateWindow(TRACKBAR_CLASS, TEXT(""), WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_HORZ | TBS_ENABLESELRANGE, SLIDER_CX, SLIDER_CY, SLIDER_W, SLIDER_H, hWnd, (HMENU)SLIDER_ID, hInst, 0); if (!slider) { MessageBox(0, 0, TEXT( "CreateWindow() Error!" ), 0); return FALSE; } /* Sets slider limits */ SendMessage(slider, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(slider_min, slider_max)); UpdateWindow(slider); enable_but(BUTREC_ID); EnableWindow(slider, FALSE); break; /* Implements slider logic */ case WM_HSCROLL: { switch (LOWORD(wParam)) { case SB_ENDSCROLL: break; case SB_PAGERIGHT: case SB_PAGELEFT: case TB_THUMBTRACK: /* If the user touch the slider bar, set the audio start position properly */ slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0); slid_samp = (__int64)slider_pos * (__int64)samples_max; AUD_BUF->set_position(AUD_BUF->audinfo().bytes_in_samples((unsigned int)(slid_samp / (__int64)slider_max))); InvalidateRect(hWnd, &text_rect, TRUE); break; } break; } case WM_COMMAND: wmId = LOWORD(wParam); if ((wmId >= 0) && (wmId < 5) && (butdisabled[wmId] != FALSE)) break; switch (wmId) { case ID_FILE_NEW: if (!isnew) { if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) AUD_IN->stop_recording(); if ((AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) || (AUD_OUT->current_status() == snd::WAVEOUT_PAUSED)) AUD_OUT->stop(); AUD_BUF->reset(); enable_but(BUTREC_ID); disable_but(BUTSTART_ID); disable_but(BUTEND_ID); disable_but(BUTSTOP_ID); disable_but(BUTPLAY_ID); samples_max = AUD_BUF->total_samples(); slider_pos = 0; SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_GRAYED); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_GRAYED); isnew = TRUE; display_dur = TRUE; ZeroMemory(file_path, MAX_PATH * sizeof(TCHAR)); EnableWindow(slider, FALSE); InvalidateRect(hWnd, &text_rect, TRUE); InvalidateRect(hWnd, &text2_rect, TRUE); } break; case ID_FILE_OPEN: ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); ofn.lpstrFile = file_path; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = TEXT("wav"); if (GetOpenFileName(&ofn)) { open_wav(file_path); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); EnableWindow(slider, TRUE); } InvalidateRect(hWnd, &text_rect, TRUE); InvalidateRect(hWnd, &text2_rect, TRUE); break; case ID_ABOUT: LoadStringW(hInst, IDS_APP_TITLE, szAppName, _countof(szAppName)); hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_REACTOS_SNDREC32)); ShellAboutW(hWnd, szAppName, NULL, hIcon); DestroyIcon(hIcon); break; case ID_FILE_SAVEAS: ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd ; ofn.Flags = OFN_OVERWRITEPROMPT; ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); ofn.lpstrFile = file_path; ofn.nMaxFile = MAX_PATH; ofn.lpstrDefExt = TEXT("wav"); if (GetSaveFileName (&ofn)) { write_wav(file_path); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); } break; case ID_EDIT_AUDIOPROPS: ShellExecute(NULL, NULL, _T("rundll32.exe"), _T("shell32.dll,Control_RunDLL mmsys.cpl,ShowAudioPropertySheet"), NULL, SW_SHOWNORMAL); break; case ID_FILE_EXIT: DestroyWindow(hWnd); break; /* Sndrec32 buttons routines */ case BUTSTART_ID: AUD_BUF->set_position_start(); slider_pos = 0; SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); break; case BUTEND_ID: DestroyWindow(hWnd); break; case BUTPLAY_ID: if (wout_first == false) { AUD_OUT->open(); wout_first = true; } AUD_OUT->play(); disable_but(BUTSTART_ID); disable_but(BUTEND_ID); disable_but(BUTREC_ID); disable_but(BUTPLAY_ID); SetTimer(hWnd, 1, 250, 0); SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); break; case BUTSTOP_ID: if (s_recording) { s_recording = FALSE; AUD_IN->stop_recording(); /* Resetting slider position */ slider_pos = 0; SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); samples_max = AUD_BUF->samples_received(); EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED); enable_but(BUTSTART_ID); enable_but(BUTEND_ID); enable_but(BUTREC_ID); enable_but(BUTPLAY_ID); EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); EnableWindow(slider, TRUE); display_dur = FALSE; AUD_BUF->truncate(); InvalidateRect(hWnd, &text_rect, TRUE); InvalidateRect(wave_win, 0, TRUE); } else { AUD_OUT->pause(); enable_but(BUTSTART_ID); enable_but(BUTEND_ID); enable_but(BUTREC_ID); enable_but(BUTPLAY_ID); } KillTimer(hWnd, 1); KillTimer(hWnd, WAVEBAR_TIMERID); InvalidateRect(hWnd, &text_rect, TRUE); break; case BUTREC_ID: if (win_first == false) { AUD_IN->open(); win_first = true; } s_recording = TRUE; samples_max = AUD_BUF->total_samples(); AUD_IN->start_recording(); enable_but(BUTSTOP_ID); disable_but(BUTSTART_ID); disable_but(BUTEND_ID); disable_but(BUTREC_ID); disable_but(BUTPLAY_ID); isnew = FALSE; EnableWindow(slider, FALSE); SetTimer(hWnd, 1, 150, 0); SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_TIMER: switch (wParam) { case 1: if (stopped_flag) { KillTimer(hWnd, 1); KillTimer(hWnd, WAVEBAR_TIMERID); slider_pos = 0; enable_but(BUTPLAY_ID); stopped_flag = FALSE; } SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); InvalidateRect(hWnd, &text_rect, TRUE); break; case WAVEBAR_TIMERID: InvalidateRect(wave_win, 0, TRUE); SendMessage(wave_win, WM_USER, 0, 0); break; } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); font = CreateFontIndirect(&s_info.lfMenuFont); oldfont = (HFONT) SelectObject(hdc, font); SetBkMode(hdc, TRANSPARENT); if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) { gprintf(str_tmp, MAX_LOADSTRING, str_pos, (float)((float)AUD_BUF->bytes_recorded() / (float)AUD_BUF->audinfo().byte_rate())); } else if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) { gprintf(str_tmp, MAX_LOADSTRING, str_pos, (float)((float)AUD_BUF->bytes_played() / (float)AUD_BUF->audinfo().byte_rate())); } else { gprintf(str_tmp, MAX_LOADSTRING, str_pos, (float)((((float)slider_pos * (float)samples_max) / (float)slider_max) / (float)AUD_BUF->audinfo().sample_rate())); } ExtTextOut(hdc, STRPOS_X, STRPOS_Y, 0, 0, str_tmp, _tcslen(str_tmp), 0); if (display_dur) { gprintf(str_tmp, MAX_LOADSTRING, str_dur, AUD_BUF->fseconds_total()); } else { gprintf(str_tmp, MAX_LOADSTRING, str_dur, AUD_BUF->fseconds_recorded()); } ExtTextOut(hdc, STRDUR_X, STRDUR_Y, 0, 0, str_tmp, _tcslen(str_tmp), 0); gprintf(str_tmp, MAX_LOADSTRING, str_buf, (float)((float)AUD_BUF->mem_size() / 1024.0f)); ExtTextOut(hdc, STRBUF_X, STRBUF_Y, 0, 0, str_tmp, _tcslen(str_tmp), 0); gprintf(str_tmp, MAX_LOADSTRING, str_fmt, (float)((float)AUD_BUF->audinfo().sample_rate() / 1000.0f), AUD_BUF->audinfo().bits(), AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo); ExtTextOut(hdc, STRFMT_X, STRFMT_Y, 0, 0, str_tmp, _tcslen(str_tmp), 0); gprintf(str_tmp, MAX_LOADSTRING, str_chan, AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono); ExtTextOut(hdc, STRCHAN_X, STRCHAN_Y, 0, 0, str_tmp, _tcslen(str_tmp), 0); SelectObject(hdc, oldfont); DeleteObject(font); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } void l_play_finished(void) { stopped_flag = true; enable_but(BUTSTART_ID); enable_but(BUTEND_ID); enable_but(BUTREC_ID); enable_but(BUTPLAY_ID); InvalidateRect(wave_win, 0, TRUE); } void l_audio_arrival(unsigned int samples_arrival) { slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max); } void l_buffer_resized(unsigned int new_size) { } VOID enable_but(DWORD id) { butdisabled[id] = FALSE; SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[id]); } VOID disable_but(DWORD id) { butdisabled[id] = TRUE; SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps_dis[id]); } BOOL open_wav(TCHAR *f) { HANDLE file; riff_hdr r; wave_hdr w; data_chunk d; BOOL b; DWORD bytes_recorded_in_wav = 0; DWORD is_read = 0; file = CreateFile(f, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (!file) { MessageBox(main_win, TEXT("Cannot open file. CreateFile() error."), TEXT("ERROR"), MB_OK | MB_ICONERROR); return FALSE; } b = ReadFile(file, (LPVOID)&r, sizeof(r), &is_read, 0); if (!b) { MessageBox(main_win, TEXT("Cannot read RIFF header."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } b = ReadFile(file, (LPVOID)&w, sizeof(w), &is_read, 0); if (!b) { MessageBox(main_win, TEXT("Cannot read WAVE header."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } b = ReadFile(file, (LPVOID)&d, sizeof(d), &is_read, 0); if (!b) { MessageBox(main_win, TEXT("Cannot read WAVE subchunk."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } bytes_recorded_in_wav = r.chunksize - 36; if (bytes_recorded_in_wav == 0) { MessageBox(main_win, TEXT("Cannot read file. No audio data."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } snd::audio_format openfmt(w.SampleRate, w.BitsPerSample, w.NumChannels); AUD_BUF->clear(); AUD_BUF->alloc_bytes(bytes_recorded_in_wav); b = ReadFile(file, (LPVOID)AUD_BUF->audio_buffer(), bytes_recorded_in_wav, &is_read, 0); AUD_BUF->set_b_received(bytes_recorded_in_wav); if ((!b) || (is_read != bytes_recorded_in_wav)) { MessageBox(main_win, TEXT("Cannot read file. Error reading audio data."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); AUD_BUF->reset(); return FALSE; } CloseHandle(file); enable_but(BUTPLAY_ID); enable_but(BUTSTOP_ID); enable_but(BUTSTART_ID); enable_but(BUTEND_ID); enable_but(BUTREC_ID); samples_max = AUD_BUF->samples_received(); isnew = FALSE; return TRUE; } BOOL write_wav(TCHAR *f) { HANDLE file; DWORD written; BOOL is_writ; int i; riff_hdr r; wave_hdr w; data_chunk d; file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); if (!file) { i = MessageBox(main_win, TEXT("File already exist. Overwrite it?"), TEXT("Warning"), MB_YESNO | MB_ICONQUESTION); if (i == IDYES) { file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (!file) { MessageBox(main_win, TEXT("File Error, CreateFile() failed."), TEXT("ERROR"), MB_OK | MB_ICONERROR); return FALSE; } } else return FALSE; } r.magic = 0x46464952; r.format = 0x45564157; r.chunksize = 36 + AUD_BUF->bytes_recorded(); w.Subchunkid = 0x20746d66; w.Subchunk1Size = 16; w.AudioFormat = 1; w.NumChannels = AUD_BUF->audinfo().channels(); w.SampleRate = AUD_BUF->audinfo().sample_rate(); w.ByteRate = AUD_BUF->audinfo().byte_rate(); w.BlockAlign = AUD_BUF->audinfo().block_align(); w.BitsPerSample = AUD_BUF->audinfo().bits(); d.subc = 0x61746164; d.subc_size = AUD_BUF->bytes_recorded(); /* Writing headers */ is_writ = WriteFile(file, (LPCVOID)&r, sizeof(r), &written, 0); if (!is_writ) { MessageBox(main_win, TEXT("File Error, WriteFile() failed."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } is_writ = WriteFile(file, (LPCVOID)&w, sizeof(w), &written, 0); if (!is_writ) { MessageBox(main_win, TEXT("File Error, WriteFile() failed."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } is_writ = WriteFile(file, (LPCVOID)&d, sizeof(d), &written, 0); if (!is_writ) { MessageBox(main_win, TEXT("File Error, WriteFile() failed."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } is_writ = WriteFile(file, (LPCVOID)AUD_BUF->audio_buffer(), AUD_BUF->bytes_recorded(), &written, 0); if (!is_writ) { MessageBox(main_win, TEXT("File Error, WriteFile() failed."), TEXT("ERROR"), MB_OK | MB_ICONERROR); CloseHandle(file); return FALSE; } CloseHandle(file); return TRUE; }