/* 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) */ #ifndef _UNICODE #define gprintf _snprintf #else #define gprintf _snwprintf #endif #include "stdafx.h" #include "sndrec32.h" 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_PTR CALLBACK AboutDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: EndDialog(hWnd, 0); return TRUE; } break; case WM_CLOSE: EndDialog(hWnd, 0); return TRUE; } return FALSE; } 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(); 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 defaul 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( msg.hwnd, 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 = CreateWindow( TEXT( "sndrec32_wave" ), TEXT(""), WS_DLGFRAME|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; 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 ); 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 ); } 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; long long slid_samp = 0; // // 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( "CreateWindow() 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)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] == TRUE )) break; switch ( wmId ) { case ID_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: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc); return TRUE; 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_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 ); 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, ETO_OPAQUE, 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, ETO_OPAQUE, 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, ETO_OPAQUE, 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, ETO_OPAQUE, 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, ETO_OPAQUE, 0, str_tmp, _tcslen( str_tmp ), 0 ); 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; }