reactos/base/applications/sndrec32/sndrec32.cpp
Amine Khaldi c424146e2c Create a branch for cmake bringup.
svn path=/branches/cmake-bringup/; revision=48236
2010-07-24 18:52:44 +00:00

1566 lines
32 KiB
C++

/* 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 = ( abs(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, wmEvent;
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 );
wmEvent = HIWORD( 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 );
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;
}