* Added wavebar
[reactos.git] / reactos / base / applications / sndrec32 / sndrec32.cpp
1 /* PROJECT: ReactOS sndrec32
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/sndrec32/sndrec32.cpp
4 * PURPOSE: Sound recording
5 * PROGRAMMERS: Marco Pagliaricci (irc: rendar)
6 */
7
8 #ifndef _UNICODE
9 #define gprintf _snprintf
10 #else
11 #define gprintf _snwprintf
12 #endif
13
14 #include "stdafx.h"
15 #include "sndrec32.h"
16
17
18
19
20
21 HINSTANCE hInst;
22 TCHAR szTitle[MAX_LOADSTRING];
23 TCHAR szWindowClass[MAX_LOADSTRING];
24
25
26 ATOM MyRegisterClass( HINSTANCE hInstance );
27 ATOM MyRegisterClass_wave( HINSTANCE hInstance );
28 BOOL InitInstance( HINSTANCE, int );
29 BOOL InitInstance_wave( HWND, HINSTANCE, int );
30 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
31 LRESULT CALLBACK WndProc_wave( HWND, UINT, WPARAM, LPARAM );
32 INT_PTR CALLBACK About( HWND, UINT, WPARAM, LPARAM );
33
34 BOOL win_first, wout_first;
35
36 HWND main_win;
37 HWND wave_win;
38 HWND slider;
39 HWND buttons[5];
40 HBITMAP butbmps[5];
41 HBITMAP butbmps_dis[5];
42 WNDPROC buttons_std_proc;
43
44 BOOL butdisabled[5];
45 BOOL stopped_flag;
46 BOOL isnew;
47 BOOL display_dur;
48
49
50 DWORD slider_pos;
51 WORD slider_min;
52 WORD slider_max;
53
54 DWORD samples_max;
55
56 OPENFILENAME ofn;
57 TCHAR file_path[MAX_PATH];
58 TCHAR str_pos[MAX_LOADSTRING];
59 TCHAR str_dur[MAX_LOADSTRING];
60 TCHAR str_buf[MAX_LOADSTRING];
61 TCHAR str_fmt[MAX_LOADSTRING];
62 TCHAR str_chan[MAX_LOADSTRING];
63
64 TCHAR str_mono[10];
65 TCHAR str_stereo[10];
66
67 BOOL path_set;
68
69 snd::audio_membuffer * AUD_BUF;
70 snd::audio_waveout * AUD_OUT;
71 snd::audio_wavein * AUD_IN;
72
73
74 BOOL s_recording;
75
76
77 NONCLIENTMETRICS s_info;
78
79
80 RECT text_rect;
81 RECT text2_rect;
82 RECT cli;
83
84
85
86
87
88 int APIENTRY _tWinMain(HINSTANCE hInstance,
89 HINSTANCE hPrevInstance,
90 LPTSTR lpCmdLine,
91 int nCmdShow)
92 {
93
94 UNREFERENCED_PARAMETER(hPrevInstance);
95 UNREFERENCED_PARAMETER(lpCmdLine);
96
97
98 MSG msg;
99 HACCEL hAccelTable;
100
101 s_info.cbSize = sizeof( NONCLIENTMETRICS );
102
103 InitCommonControls();
104
105 win_first = wout_first = FALSE;
106
107 text_rect.left = REFRESHA_X;
108 text_rect.top = REFRESHA_Y;
109 text_rect.right = REFRESHA_CX;
110 text_rect.bottom = REFRESHA_CY;
111
112 text2_rect.left = REFRESHB_X;
113 text2_rect.top = REFRESHB_Y;
114 text2_rect.right = REFRESHB_CX;
115 text2_rect.bottom = REFRESHB_CY;
116
117 //
118 // Retrieving defaul system font, and others
119 // system informations.
120 //
121
122 SystemParametersInfo(
123 SPI_GETNONCLIENTMETRICS,
124 sizeof( NONCLIENTMETRICS ),
125 &s_info,
126 0
127 );
128
129 //
130 // Set font size
131 //
132
133 s_info.lfMenuFont.lfHeight = 14;
134
135 //
136 // Inits buttons bitmaps
137 //
138
139 butbmps[0] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_START ));
140 butbmps[1] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_END ));
141 butbmps[2] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_PLAY ));
142 butbmps[3] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_STOP ));
143 butbmps[4] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_REC ));
144
145 butbmps_dis[0] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_START_DIS ));
146 butbmps_dis[1] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_END_DIS ));
147 butbmps_dis[2] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_PLAY_DIS ));
148 butbmps_dis[3] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_STOP_DIS ));
149 butbmps_dis[4] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_REC_DIS ));
150
151
152
153 //
154 // Inits audio devices and buffers
155 //
156
157 snd::audio_membuffer AUD_buffer( snd::A44100_16BIT_STEREO );
158 snd::audio_waveout AUD_waveout( snd::A44100_16BIT_STEREO, AUD_buffer );
159 snd::audio_wavein AUD_wavein( snd::A44100_16BIT_STEREO, AUD_buffer );
160
161 AUD_buffer.play_finished = l_play_finished;
162 AUD_buffer.audio_arrival = l_audio_arrival;
163 AUD_buffer.buffer_resized = l_buffer_resized;
164
165 AUD_buffer.alloc_seconds( INITIAL_BUFREC_SECONDS );
166
167 AUD_IN = &AUD_wavein;
168 AUD_OUT = &AUD_waveout;
169 AUD_BUF = &AUD_buffer;
170
171 //
172 // Inits slider default parameters
173 //
174
175 slider_pos = 0;
176 slider_min = 0;
177 slider_max = SLIDER_W;
178
179
180 stopped_flag = FALSE;
181 path_set = FALSE;
182 isnew = TRUE;
183 display_dur = TRUE;
184
185 samples_max = AUD_buffer.total_samples();
186
187 s_recording = false;
188
189 //
190 // Inits strings
191 //
192
193 LoadString( hInstance,
194 IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
195
196 LoadString( hInstance,
197 IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING );
198
199
200 LoadString( hInstance,
201 IDS_STRPOS, str_pos, MAX_LOADSTRING );
202
203
204 LoadString( hInstance,
205 IDS_STRDUR, str_dur, MAX_LOADSTRING );
206
207 LoadString( hInstance,
208 IDS_STRBUF, str_buf, MAX_LOADSTRING );
209
210 LoadString( hInstance,
211 IDS_STRFMT, str_fmt, MAX_LOADSTRING );
212
213 LoadString( hInstance,
214 IDS_STRCHAN, str_chan, MAX_LOADSTRING );
215
216 LoadString( hInstance,
217 IDS_STRMONO, str_mono, 10 );
218
219 LoadString( hInstance,
220 IDS_STRSTEREO, str_stereo, 10 );
221
222
223 //
224 // Registers sndrec32 window class
225 //
226
227 MyRegisterClass( hInstance );
228
229 MyRegisterClass_wave( hInstance );
230
231
232 if ( !InitInstance( hInstance, nCmdShow ))
233 {
234 MessageBox( 0, TEXT( "CreateWindow() Error!" ), TEXT( "ERROR" ), MB_ICONERROR );
235 return FALSE;
236 }
237
238 //
239 // Loads key accelerators
240 //
241
242 hAccelTable = LoadAccelerators(hInstance,
243 MAKEINTRESOURCE( IDC_REACTOS_SNDREC32 ));
244
245
246
247 //
248 // Starts main loop
249 //
250
251 while ( GetMessage( &msg, NULL, 0, 0 ))
252 {
253 if ( !TranslateAccelerator( msg.hwnd, hAccelTable, &msg ))
254 {
255 TranslateMessage( &msg );
256 DispatchMessage( &msg );
257 }
258 }
259
260 if ( wout_first )
261 {
262 AUD_waveout.close();
263
264 }
265
266
267 if ( win_first )
268 {
269 AUD_wavein.close();
270
271 }
272
273 AUD_buffer.clear();
274
275 return ( int )msg.wParam;
276 }
277
278
279
280
281 ATOM
282 MyRegisterClass( HINSTANCE hInstance )
283 {
284 WNDCLASSEX wcex;
285
286 wcex.cbSize = sizeof(WNDCLASSEX);
287
288 wcex.style = CS_HREDRAW | CS_VREDRAW;
289 wcex.lpfnWndProc = WndProc;
290 wcex.cbClsExtra = 0;
291 wcex.cbWndExtra = 0;
292 wcex.hInstance = hInstance;
293 wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_SNDREC32 ));
294 wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
295 wcex.hbrBackground = (HBRUSH)( 16 );
296 wcex.lpszMenuName = MAKEINTRESOURCE( IDR_MENU1 );
297 wcex.lpszClassName = szWindowClass;
298 wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_SNDREC32 ));
299
300
301 return RegisterClassEx( &wcex );
302 }
303
304 BOOL
305 InitInstance( HINSTANCE hInstance, int nCmdShow )
306 {
307 HWND hWnd;
308
309 hInst = hInstance;
310
311 hWnd = CreateWindow(
312 szWindowClass,
313 szTitle,
314 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
315 CW_USEDEFAULT,
316 CW_USEDEFAULT,
317 MAINWINDOW_W,
318 MAINWINDOW_H,
319 NULL, NULL,
320 hInstance, NULL
321 );
322
323 if (!hWnd)
324 {
325 return FALSE;
326 }
327
328 ShowWindow(hWnd, nCmdShow);
329 UpdateWindow(hWnd);
330
331 main_win = hWnd;
332
333
334 return TRUE;
335 }
336
337
338
339
340
341 ATOM
342 MyRegisterClass_wave( HINSTANCE hInstance )
343 {
344 WNDCLASSEX wcex;
345
346 wcex.cbSize = sizeof( WNDCLASSEX );
347
348 wcex.style = CS_HREDRAW | CS_VREDRAW;
349 wcex.lpfnWndProc = WndProc_wave;
350 wcex.cbClsExtra = 0;
351 wcex.cbWndExtra = 0;
352 wcex.hInstance = hInstance;
353 wcex.hIcon = 0;
354 wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
355 wcex.hbrBackground = ( HBRUSH )GetStockObject( BLACK_BRUSH );
356 wcex.lpszMenuName = 0;
357 wcex.lpszClassName = TEXT( "sndrec32_wave" );
358 wcex.hIconSm = 0;
359
360
361 return RegisterClassEx( &wcex );
362 }
363
364 BOOL
365 InitInstance_wave( HWND f, HINSTANCE hInstance, int nCmdShow )
366 {
367 HWND hWnd;
368
369 hInst = hInstance;
370
371 hWnd = CreateWindow(
372 TEXT( "sndrec32_wave" ),
373 TEXT(""),
374 WS_DLGFRAME|WS_VISIBLE|WS_CHILD,
375 WAVEBAR_X,
376 WAVEBAR_Y,
377 WAVEBAR_CX,
378 WAVEBAR_CY,
379 f, ( HMENU ) 8,
380 hInstance, 0
381 );
382
383 if ( !hWnd )
384 {
385 return FALSE;
386 }
387
388 ShowWindow( hWnd, nCmdShow );
389 UpdateWindow( hWnd );
390
391 wave_win = hWnd;
392
393
394 return TRUE;
395 }
396
397
398 LRESULT CALLBACK
399 WndProc_wave( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
400 {
401 PAINTSTRUCT ps;
402 HDC hdc;
403 HPEN pen;
404
405
406
407 unsigned int max_h = ( cli.bottom / 2 );
408 unsigned int samples;
409 unsigned int x, line_h;
410
411
412
413 switch ( message )
414 {
415
416
417 case WM_CREATE:
418
419
420 GetClientRect( hWnd, &cli );
421
422 break;
423
424
425 case WM_PAINT:
426
427 //
428 // Initialize hdc objects
429 //
430
431 hdc = BeginPaint( hWnd, &ps );
432
433 pen = ( HPEN ) CreatePen( PS_SOLID, 1, WAVEBAR_COLOR );
434
435 SelectObject( hdc, ( HBRUSH )pen );
436
437 if ( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING )
438 {
439
440 samples = AUD_OUT->tot_samples_buf();
441
442
443 for ( unsigned int i = 0; i < WAVEBAR_CX; ++i )
444 {
445
446 x = ( i * samples ) / WAVEBAR_CX;
447
448 line_h = ( abs(AUD_OUT->nsample( x )) * max_h ) / AUD_OUT->samplevalue_max();
449
450
451 if ( line_h )
452 {
453 MoveToEx( hdc, i, max_h, 0 );
454 LineTo( hdc, i, max_h - ( line_h * 2 ));
455 LineTo( hdc, i, max_h + ( line_h * 2 ));
456 } else
457 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
458
459 }
460
461
462 } else if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING ) {
463
464
465 samples = AUD_IN->tot_samples_buf();
466
467
468 for ( unsigned int i = 0; i < WAVEBAR_CX; ++i )
469 {
470
471 x = ( i * samples ) / WAVEBAR_CX;
472
473 line_h = ( AUD_IN->nsample( x ) * max_h ) / AUD_IN->samplevalue_max();
474
475
476 if ( line_h )
477 {
478 MoveToEx( hdc, i, max_h, 0 );
479 LineTo( hdc, i, max_h - ( line_h * 2 ));
480 LineTo( hdc, i, max_h + ( line_h * 2 ));
481 } else
482 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
483
484 }
485
486
487 } else {
488
489 //
490 // In standby mode draw a simple line.
491 //
492
493 MoveToEx( hdc, 0, cli.bottom / 2, 0 );
494 LineTo( hdc, WAVEBAR_CX, cli.bottom / 2 );
495
496 }
497
498
499 DeleteObject( pen );
500
501 EndPaint( hWnd, &ps );
502
503 break;
504
505
506 case WM_USER:
507
508
509 break;
510
511
512 default:
513 return DefWindowProc( hWnd, message, wParam, lParam );
514
515
516 }
517
518
519 return 0;
520
521 }
522
523
524
525 LRESULT CALLBACK
526 WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
527 {
528 int wmId, wmEvent;
529 TCHAR str_tmp[MAX_LOADSTRING];
530 PAINTSTRUCT ps;
531 HDC hdc;
532 HFONT font;
533 long long slid_samp = 0;
534
535
536
537 //
538 // Checking for global pointers to buffer and
539 // io audio devices.
540 //
541
542 if (( !AUD_IN ) || ( !AUD_OUT ) || ( !AUD_BUF ))
543 {
544 MessageBox( 0, TEXT("Buffer Error"), 0, 0 );
545 return 1;
546 }
547
548
549 switch ( message )
550 {
551
552
553 case WM_CREATE:
554
555
556 //
557 // Creating the wave bar
558 //
559
560 if ( !InitInstance_wave( hWnd, hInst, SW_SHOWNORMAL ))
561 {
562 MessageBox(
563 0,
564 TEXT( "CreateWindow() Error!" ),
565 TEXT( "ERROR" ),
566 MB_ICONERROR
567 );
568
569 return FALSE;
570 }
571
572
573
574
575 //
576 // Creating ALL the buttons
577 //
578
579 for ( int i = 0; i < 5; ++ i )
580 {
581
582 buttons[i] = CreateWindow(
583 TEXT("button"),
584 TEXT(""),
585 WS_CHILD|WS_VISIBLE|BS_BITMAP,
586 BUTTONS_CX + ( i * (BUTTONS_W+((i == 0)?0:BUTTONS_SPACE))),
587 BUTTONS_CY, BUTTONS_W, BUTTONS_H, hWnd,
588 (HMENU)i, hInst, 0
589 );
590
591 if ( !buttons[i] )
592 {
593 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0);
594 return FALSE;
595
596 }
597
598
599 //
600 // Realize the button bmp image
601 //
602
603 SendMessage(buttons[i], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[i]);
604
605 UpdateWindow( buttons[i] );
606
607 disable_but( i );
608
609 }
610
611
612 //
613 // Creating the SLIDER window
614 //
615
616 slider = CreateWindow(
617 TRACKBAR_CLASS,
618 TEXT(""),
619 WS_CHILD|WS_VISIBLE|TBS_NOTICKS|TBS_HORZ|TBS_ENABLESELRANGE,
620 SLIDER_CX, SLIDER_CY, SLIDER_W, SLIDER_H, hWnd,
621 ( HMENU )SLIDER_ID, hInst, 0
622 );
623
624
625 if ( !slider )
626 {
627 MessageBox( 0, 0, TEXT( "CreateWindow() Error!" ), 0 );
628 return FALSE;
629
630 }
631
632
633 //
634 // Sets slider limits
635 //
636
637
638 SendMessage(
639 slider,
640 TBM_SETRANGE,
641 ( WPARAM )TRUE,
642 ( LPARAM )MAKELONG( slider_min, slider_max )
643 );
644
645
646 UpdateWindow( slider );
647
648 enable_but( BUTREC_ID );
649
650 EnableWindow( slider, FALSE );
651
652
653
654
655 break;
656
657
658
659 //
660 // Implements slider logic
661 //
662
663 case WM_HSCROLL :
664 {
665 switch( LOWORD( wParam ))
666 {
667
668 case SB_ENDSCROLL:
669 break;
670
671 case SB_PAGERIGHT:
672 case SB_PAGELEFT:
673 case TB_THUMBTRACK:
674
675
676 //
677 // If the user touch the slider bar,
678 // set the audio start position properly
679 //
680
681
682 slider_pos = SendMessage( slider, TBM_GETPOS, 0, 0 );
683
684 slid_samp = ( __int64 )slider_pos * ( __int64 )samples_max;
685
686 AUD_BUF->set_position(
687 AUD_BUF->audinfo().bytes_in_samples(
688 ( unsigned int )( slid_samp / ( __int64 )slider_max )
689 )
690 );
691
692 InvalidateRect( hWnd, &text_rect, TRUE );
693
694
695 break;
696
697 }
698
699 break;
700 }
701
702
703
704
705
706
707 case WM_COMMAND:
708
709 wmId = LOWORD( wParam );
710 wmEvent = HIWORD( wParam );
711
712 if (( wmId >= 0 ) && ( wmId < 5 ) && ( butdisabled[wmId] == TRUE ))
713 break;
714
715 switch ( wmId )
716 {
717
718 case ID_NEW:
719
720 if ( !isnew )
721 {
722
723 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
724 AUD_IN->stop_recording();
725
726
727 if (( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) ||
728 ( AUD_OUT->current_status() == snd::WAVEOUT_PAUSED ))
729 AUD_OUT->stop();
730
731
732 AUD_BUF->reset();
733
734 enable_but( BUTREC_ID );
735 disable_but( BUTSTART_ID );
736 disable_but( BUTEND_ID );
737 disable_but( BUTSTOP_ID );
738 disable_but( BUTPLAY_ID );
739
740
741 samples_max = AUD_BUF->total_samples();
742 slider_pos = 0;
743
744 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
745
746 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_GRAYED );
747 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_GRAYED );
748
749 isnew = TRUE;
750 display_dur = TRUE;
751
752 ZeroMemory( file_path, MAX_PATH );
753
754 EnableWindow( slider, FALSE );
755
756 InvalidateRect( hWnd, &text_rect, TRUE );
757 InvalidateRect( hWnd, &text2_rect, TRUE );
758
759 }
760
761
762
763 break;
764
765
766
767
768 case ID_FILE_OPEN:
769
770 ZeroMemory( &ofn, sizeof( ofn ));
771
772 ofn.lStructSize = sizeof( ofn );
773 ofn.hwndOwner = hWnd;
774 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
775 ofn.lpstrFile = file_path;
776 ofn.nMaxFile = MAX_PATH;
777 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
778 ofn.lpstrDefExt = TEXT("wav");
779
780 if( GetOpenFileName( &ofn ))
781 {
782 open_wav( file_path );
783 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
784 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
785
786 EnableWindow( slider, TRUE );
787
788 }
789
790 InvalidateRect( hWnd, &text_rect, TRUE );
791 InvalidateRect( hWnd, &text2_rect, TRUE );
792
793 break;
794
795
796
797
798 case ID__ABOUT:
799
800
801
802 break;
803
804
805 case ID_FILE_SAVEAS:
806
807 ZeroMemory( &ofn, sizeof( ofn ));
808
809 ofn.lStructSize = sizeof( ofn );
810 ofn.hwndOwner = hWnd ;
811 ofn.Flags = OFN_OVERWRITEPROMPT;
812 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
813 ofn.lpstrFile = file_path;
814 ofn.nMaxFile = MAX_PATH;
815
816 ofn.lpstrDefExt = TEXT("wav");
817
818 if ( GetSaveFileName ( &ofn ))
819 {
820 write_wav( file_path );
821
822 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
823 }
824
825 break;
826
827 case ID_EXIT:
828 DestroyWindow( hWnd );
829 break;
830
831
832 //
833 // Sndrec32 buttons routines
834 //
835
836 case BUTSTART_ID:
837
838 AUD_BUF->set_position_start();
839
840 slider_pos = 0;
841
842 SendMessage( slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos );
843
844 break;
845
846
847 case BUTEND_ID:
848 DestroyWindow( hWnd );
849 break;
850
851 case BUTPLAY_ID:
852
853 if ( wout_first == false )
854 {
855 AUD_OUT->open();
856 wout_first = true;
857 }
858
859
860 AUD_OUT->play();
861
862 disable_but( BUTSTART_ID );
863 disable_but( BUTEND_ID );
864 disable_but( BUTREC_ID );
865 disable_but( BUTPLAY_ID );
866
867
868 SetTimer( hWnd, 1, 250, 0 );
869 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
870
871 break;
872
873 case BUTSTOP_ID:
874 if ( s_recording )
875 {
876 s_recording = FALSE;
877
878 AUD_IN->stop_recording();
879
880
881
882 //
883 // Resetting slider position
884 //
885
886 slider_pos = 0;
887 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
888
889
890 samples_max = AUD_BUF->samples_received();
891
892 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED );
893
894
895 enable_but( BUTSTART_ID );
896 enable_but( BUTEND_ID );
897 enable_but( BUTREC_ID );
898 enable_but( BUTPLAY_ID );
899
900 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
901 EnableWindow( slider, TRUE );
902
903 display_dur = FALSE;
904
905 AUD_BUF->truncate();
906
907 InvalidateRect( hWnd, &text_rect, TRUE );
908 InvalidateRect( wave_win, 0, TRUE );
909
910
911 } else {
912
913 AUD_OUT->pause();
914
915 enable_but( BUTSTART_ID );
916 enable_but( BUTEND_ID );
917 enable_but( BUTREC_ID );
918 enable_but( BUTPLAY_ID );
919
920 }
921
922 KillTimer( hWnd, 1 );
923 KillTimer( hWnd, WAVEBAR_TIMERID );
924
925 InvalidateRect( hWnd, &text_rect, TRUE );
926
927 break;
928
929 case BUTREC_ID:
930
931 if ( win_first == false )
932 {
933 AUD_IN->open();
934 win_first = true;
935 }
936
937 s_recording = TRUE;
938
939 samples_max = AUD_BUF->total_samples();
940
941 AUD_IN->start_recording();
942
943 enable_but( BUTSTOP_ID );
944
945 disable_but( BUTSTART_ID );
946 disable_but( BUTEND_ID );
947 disable_but( BUTREC_ID );
948 disable_but( BUTPLAY_ID );
949
950 isnew = FALSE;
951
952 EnableWindow( slider, FALSE );
953
954 SetTimer( hWnd, 1, 150, 0 );
955
956 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
957
958 break;
959
960
961 default:
962 return DefWindowProc(hWnd, message, wParam, lParam);
963 }
964 break;
965
966
967 case WM_TIMER:
968
969 switch ( wParam )
970 {
971
972 case 1:
973 if ( stopped_flag )
974 {
975 KillTimer( hWnd, 1 );
976 KillTimer( hWnd, WAVEBAR_TIMERID );
977 slider_pos = 0;
978
979 enable_but( BUTPLAY_ID );
980
981 stopped_flag = FALSE;
982 }
983
984
985
986 SendMessage(
987 slider,
988 TBM_SETPOS,
989 ( WPARAM ) TRUE,
990 ( LPARAM ) slider_pos
991 );
992
993 InvalidateRect( hWnd, &text_rect, TRUE );
994 break;
995
996
997
998 case WAVEBAR_TIMERID:
999 InvalidateRect( wave_win, 0, TRUE );
1000 SendMessage( wave_win, WM_USER, 0, 0 );
1001 break;
1002
1003 }
1004
1005 break;
1006
1007
1008
1009 case WM_PAINT:
1010
1011
1012 hdc = BeginPaint(hWnd, &ps);
1013
1014
1015 font = CreateFontIndirect( &s_info.lfMenuFont );
1016
1017
1018 SelectObject( hdc, font );
1019
1020 SetBkMode( hdc, TRANSPARENT );
1021
1022
1023 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
1024 {
1025 gprintf(
1026 str_tmp,
1027 MAX_LOADSTRING,
1028 str_pos,
1029 ( float )(( float )AUD_BUF->bytes_recorded( ) / ( float )AUD_BUF->audinfo().byte_rate( ))
1030 );
1031
1032 } else if ( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) {
1033
1034 gprintf(
1035 str_tmp,
1036 MAX_LOADSTRING,
1037 str_pos,
1038 ( float )(( float )AUD_BUF->bytes_played() / ( float )AUD_BUF->audinfo().byte_rate( ))
1039 );
1040
1041 } else {
1042
1043 gprintf(
1044 str_tmp,
1045 MAX_LOADSTRING,
1046 str_pos,
1047 ( float )(((( float )slider_pos * ( float )samples_max ) / ( float )slider_max ) / ( float )AUD_BUF->audinfo().sample_rate())
1048 );
1049 }
1050
1051
1052 ExtTextOut( hdc, STRPOS_X, STRPOS_Y, ETO_OPAQUE,
1053 0, str_tmp, _tcslen( str_tmp ), 0 );
1054
1055
1056 if ( display_dur )
1057 {
1058
1059 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1060 AUD_BUF->fseconds_total( ));
1061
1062 } else {
1063
1064
1065 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1066 AUD_BUF->fseconds_recorded( ));
1067 }
1068
1069
1070
1071 ExtTextOut( hdc, STRDUR_X, STRDUR_Y, ETO_OPAQUE,
1072 0, str_tmp, _tcslen( str_tmp ), 0 );
1073
1074
1075
1076 gprintf(
1077 str_tmp,
1078 MAX_LOADSTRING,
1079 str_buf,
1080 ( float )(( float )AUD_BUF->mem_size() / 1024.0f )
1081 );
1082
1083
1084 ExtTextOut( hdc, STRBUF_X, STRBUF_Y, ETO_OPAQUE,
1085 0, str_tmp, _tcslen( str_tmp ), 0 );
1086
1087
1088
1089 gprintf(
1090 str_tmp,
1091 MAX_LOADSTRING,
1092 str_fmt,
1093 ( float )(( float )AUD_BUF->audinfo().sample_rate() / 1000.0f ),
1094 AUD_BUF->audinfo().bits(),
1095 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo
1096 );
1097
1098
1099 ExtTextOut( hdc, STRFMT_X, STRFMT_Y, ETO_OPAQUE,
1100 0, str_tmp, _tcslen( str_tmp ), 0 );
1101
1102
1103
1104 gprintf(
1105 str_tmp,
1106 MAX_LOADSTRING,
1107 str_chan,
1108 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono
1109 );
1110
1111
1112 ExtTextOut( hdc, STRCHAN_X, STRCHAN_Y, ETO_OPAQUE,
1113 0, str_tmp, _tcslen( str_tmp ), 0 );
1114
1115
1116
1117 DeleteObject( font );
1118
1119 EndPaint(hWnd, &ps);
1120
1121
1122 break;
1123
1124
1125
1126
1127 case WM_DESTROY:
1128 PostQuitMessage(0);
1129 break;
1130 default:
1131 return DefWindowProc( hWnd, message, wParam, lParam );
1132 }
1133 return 0;
1134 }
1135
1136
1137
1138
1139
1140 void l_play_finished ( void )
1141 {
1142
1143 stopped_flag = true;
1144
1145
1146 enable_but( BUTSTART_ID );
1147 enable_but( BUTEND_ID );
1148 enable_but( BUTREC_ID );
1149 enable_but( BUTPLAY_ID );
1150
1151 InvalidateRect( wave_win, 0, TRUE );
1152
1153 }
1154
1155 void l_audio_arrival ( unsigned int samples_arrival )
1156 {
1157
1158
1159 slider_pos += ( DWORD ) (( slider_max * samples_arrival ) / samples_max );
1160
1161
1162 }
1163
1164 void l_buffer_resized ( unsigned int new_size )
1165 {
1166
1167
1168
1169
1170
1171 }
1172
1173 VOID enable_but( DWORD id )
1174 {
1175
1176 butdisabled[ id ] = FALSE;
1177
1178 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[ id ]);
1179
1180
1181 }
1182 VOID disable_but( DWORD id )
1183 {
1184
1185 butdisabled[ id ] = TRUE;
1186
1187 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps_dis[ id ]);
1188
1189 }
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 BOOL open_wav( TCHAR * f )
1207 {
1208
1209
1210 HANDLE file;
1211
1212 riff_hdr r;
1213 wave_hdr w;
1214 data_chunk d;
1215
1216 BOOL b;
1217
1218 DWORD bytes_recorded_in_wav = 0;
1219 DWORD is_read = 0;
1220
1221
1222 file = CreateFile(
1223 f,
1224 GENERIC_READ,
1225 0, 0,
1226 OPEN_EXISTING,
1227 FILE_ATTRIBUTE_NORMAL,
1228 0
1229 );
1230
1231
1232
1233 if ( !file )
1234 {
1235 MessageBox(
1236 main_win,
1237 TEXT("Cannot open file. CreateFile() error."),
1238 TEXT("ERROR"),
1239 MB_OK|MB_ICONERROR
1240 );
1241
1242 return FALSE;
1243 }
1244
1245
1246 b = ReadFile( file, ( LPVOID ) &r, sizeof ( r ), &is_read, 0 );
1247
1248 if ( !b )
1249 {
1250 MessageBox(
1251 main_win,
1252 TEXT("Cannot read RIFF header."),
1253 TEXT("ERROR"),
1254 MB_OK|MB_ICONERROR
1255 );
1256
1257 CloseHandle( file );
1258 return FALSE;
1259 }
1260
1261
1262 b = ReadFile( file, ( LPVOID ) &w, sizeof ( w ), &is_read, 0 );
1263
1264
1265 if ( !b )
1266 {
1267 MessageBox(
1268 main_win,
1269 TEXT("Cannot read WAVE header."),
1270 TEXT("ERROR"),
1271 MB_OK|MB_ICONERROR
1272 );
1273
1274 CloseHandle( file );
1275 return FALSE;
1276 }
1277
1278
1279
1280 b = ReadFile( file, ( LPVOID ) &d, sizeof ( d ), &is_read, 0 );
1281
1282 if ( !b )
1283 {
1284 MessageBox(
1285 main_win,
1286 TEXT("Cannot read WAVE subchunk."),
1287 TEXT("ERROR"),
1288 MB_OK|MB_ICONERROR
1289 );
1290
1291 CloseHandle( file );
1292 return FALSE;
1293 }
1294
1295 bytes_recorded_in_wav = r.chunksize - 36;
1296
1297
1298 if ( bytes_recorded_in_wav == 0 )
1299 {
1300 MessageBox(
1301 main_win,
1302 TEXT("Cannot read file. No audio data."),
1303 TEXT("ERROR"),
1304 MB_OK|MB_ICONERROR
1305 );
1306
1307 CloseHandle( file );
1308 return FALSE;
1309 }
1310
1311
1312 snd::audio_format openfmt
1313 ( w.SampleRate, w.BitsPerSample, w.NumChannels );
1314
1315
1316
1317 AUD_BUF->clear();
1318
1319
1320 AUD_BUF->alloc_bytes( bytes_recorded_in_wav );
1321
1322
1323 b = ReadFile(
1324 file,
1325 ( LPVOID ) AUD_BUF->audio_buffer(),
1326 bytes_recorded_in_wav,
1327 &is_read,
1328 0
1329 );
1330
1331
1332 AUD_BUF->set_b_received( bytes_recorded_in_wav );
1333
1334
1335 if (( !b ) || ( is_read != bytes_recorded_in_wav ))
1336 {
1337 MessageBox(
1338 main_win,
1339 TEXT("Cannot read file. Error reading audio data."),
1340 TEXT("ERROR"),
1341 MB_OK|MB_ICONERROR
1342 );
1343
1344 CloseHandle( file );
1345
1346 AUD_BUF->reset();
1347 return FALSE;
1348 }
1349
1350 CloseHandle( file );
1351
1352 enable_but( BUTPLAY_ID );
1353 enable_but( BUTSTOP_ID );
1354 enable_but( BUTSTART_ID );
1355 enable_but( BUTEND_ID );
1356 enable_but( BUTREC_ID );
1357
1358
1359 samples_max = AUD_BUF->samples_received();
1360
1361 isnew = FALSE;
1362
1363 return TRUE;
1364
1365 }
1366
1367
1368 BOOL
1369 write_wav( TCHAR * f )
1370 {
1371
1372 HANDLE file;
1373
1374
1375 DWORD written;
1376 BOOL is_writ;
1377 int i;
1378 riff_hdr r;
1379 wave_hdr w;
1380 data_chunk d;
1381
1382
1383
1384 file = CreateFile(
1385 f,
1386 GENERIC_WRITE,
1387 0, 0,
1388 CREATE_NEW,
1389 FILE_ATTRIBUTE_NORMAL,
1390 0
1391 );
1392
1393
1394
1395 if ( !file )
1396 {
1397 i = MessageBox(
1398 main_win,
1399 TEXT("File already exist. Overwrite it?"),
1400 TEXT("Warning"),
1401 MB_YESNO|MB_ICONQUESTION
1402 );
1403
1404 if ( i == IDYES )
1405 {
1406
1407 file = CreateFile(
1408 f,
1409 GENERIC_WRITE,
1410 0, 0,
1411 CREATE_ALWAYS,
1412 FILE_ATTRIBUTE_NORMAL,
1413 0
1414 );
1415
1416 if ( !file )
1417 {
1418 MessageBox(
1419 main_win,
1420 TEXT("File Error, CreateFile() failed."),
1421 TEXT("ERROR"),
1422 MB_OK|MB_ICONERROR
1423 );
1424
1425
1426 return FALSE;
1427
1428 }
1429
1430
1431 } else
1432 return FALSE;
1433 }
1434
1435
1436
1437
1438 r.magic = 0x46464952;
1439
1440
1441 r.format = 0x45564157;
1442 r.chunksize = 36 + AUD_BUF->bytes_recorded();
1443
1444
1445 w.Subchunkid = 0x20746d66;
1446
1447 w.Subchunk1Size = 16;
1448 w.AudioFormat = 1;
1449 w.NumChannels = AUD_BUF->audinfo().channels();
1450 w.SampleRate = AUD_BUF->audinfo().sample_rate();
1451 w.ByteRate = AUD_BUF->audinfo().byte_rate();
1452 w.BlockAlign = AUD_BUF->audinfo().block_align();
1453 w.BitsPerSample = AUD_BUF->audinfo().bits();
1454
1455
1456 d.subc = 0x61746164;
1457 d.subc_size = AUD_BUF->bytes_recorded();
1458
1459
1460
1461 //
1462 // Writing headers
1463 //
1464
1465
1466 is_writ = WriteFile( file, ( LPCVOID ) &r, sizeof ( r ), &written, 0 );
1467
1468 if ( !is_writ )
1469 {
1470 MessageBox(
1471 main_win,
1472 TEXT("File Error, WriteFile() failed."),
1473 TEXT("ERROR"),
1474 MB_OK|MB_ICONERROR
1475 );
1476
1477 CloseHandle( file );
1478
1479 return FALSE;
1480
1481 }
1482
1483
1484 is_writ = WriteFile( file, ( LPCVOID ) &w, sizeof ( w ), &written, 0 );
1485
1486 if ( !is_writ )
1487 {
1488 MessageBox(
1489 main_win,
1490 TEXT("File Error, WriteFile() failed."),
1491 TEXT("ERROR"),
1492 MB_OK|MB_ICONERROR
1493 );
1494
1495 CloseHandle( file );
1496
1497 return FALSE;
1498
1499 }
1500
1501
1502 is_writ = WriteFile( file, ( LPCVOID ) &d, sizeof ( d ), &written, 0 );
1503
1504
1505 if ( !is_writ )
1506 {
1507 MessageBox(
1508 main_win,
1509 TEXT("File Error, WriteFile() failed."),
1510 TEXT("ERROR"),
1511 MB_OK|MB_ICONERROR
1512 );
1513
1514 CloseHandle( file );
1515
1516 return FALSE;
1517
1518 }
1519
1520
1521
1522 is_writ = WriteFile(
1523 file,
1524 ( LPCVOID ) AUD_BUF->audio_buffer(),
1525 AUD_BUF->bytes_recorded(),
1526 &written,
1527 0
1528 );
1529
1530 if ( !is_writ )
1531 {
1532 MessageBox(
1533 main_win,
1534 TEXT("File Error, WriteFile() failed."),
1535 TEXT("ERROR"),
1536 MB_OK|MB_ICONERROR
1537 );
1538
1539 CloseHandle( file );
1540
1541 return FALSE;
1542
1543 }
1544
1545
1546 CloseHandle( file );
1547
1548 return TRUE;
1549 }