ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

audio_wavein.cpp
Go to the documentation of this file.
00001 /* PROJECT:         ReactOS sndrec32
00002  * LICENSE:         GPL - See COPYING in the top level directory
00003  * FILE:            base/applications/sndrec32/audio_wavein.cpp
00004  * PURPOSE:         Sound recording
00005  * PROGRAMMERS:     Marco Pagliaricci (irc: rendar)
00006  */
00007 
00008 
00009 
00010 #include "stdafx.h"
00011 #include "audio_wavein.hpp"
00012 
00013 
00014 
00015 _AUDIO_NAMESPACE_START_
00016 
00017 
00018 void
00019 audio_wavein::init_( void )
00020 {
00021     ZeroMemory(( LPVOID ) &wave_format, 
00022                     sizeof( WAVEFORMATEX ));
00023 
00024     wave_format.cbSize = sizeof( WAVEFORMATEX );
00025 
00026     wavein_handle = 0;
00027     recthread_id = 0;
00028     wakeup_recthread = 0;
00029 
00030     data_flushed_event = 0;
00031 
00032     buf_secs = _AUDIO_DEFAULT_WAVEINBUFSECS;
00033 
00034 
00035     status = WAVEIN_NOTREADY;
00036 }
00037 
00038 
00039 void
00040 audio_wavein::alloc_buffers_mem_( unsigned int buffs, float secs )
00041 {
00042 
00043 
00044     unsigned int 
00045         onebuf_size = 0, tot_size = 0;
00046 
00047 
00048     //
00049     // Release old memory
00050     //
00051 
00052     if ( main_buffer )
00053         delete[] main_buffer;
00054 
00055 
00056     if ( wave_headers )
00057         delete[] wave_headers;
00058 
00059 
00060 
00061     //
00062     // Calcs size of the buffers
00063     //
00064 
00065     onebuf_size = ( unsigned int )
00066         (( float )aud_info.byte_rate() * secs ); 
00067 
00068 
00069     tot_size = onebuf_size * buffs;
00070 
00071     
00072     
00073     
00074     //
00075     // Allocs memory for the audio buffers
00076     //
00077 
00078     main_buffer = new BYTE [ tot_size ];
00079 
00080 
00081 
00082     //
00083     // Allocs memory for the `WAVEHDR' structures.
00084     //
00085 
00086     wave_headers = ( WAVEHDR * ) 
00087         new BYTE [ sizeof( WAVEHDR ) * buffs ];
00088 
00089 
00090 
00091     //
00092     // Zeros memory.
00093     //
00094 
00095     ZeroMemory( main_buffer, tot_size );
00096 
00097     ZeroMemory( wave_headers, 
00098         sizeof( WAVEHDR ) * buffs );
00099 
00100 
00101     //
00102     // Updates total size of the buffers.
00103     //
00104 
00105     mb_size = tot_size;
00106 
00107 }
00108 
00109 
00110 void 
00111 audio_wavein::free_buffers_mem_( void )
00112 {
00113 
00114 
00115     //
00116     // Frees memory
00117     //
00118 
00119     if ( main_buffer )
00120         delete[] main_buffer;
00121 
00122 
00123     if ( wave_headers )
00124         delete[] wave_headers;
00125 
00126 
00127     main_buffer = 0;
00128     wave_headers = 0;
00129 
00130 }
00131 
00132 
00133 void 
00134 audio_wavein::init_headers_( void )
00135 {
00136 
00137 
00138 
00139     //
00140     // If there is no memory for memory or
00141     // headers, simply return.
00142     //
00143 
00144     if (( !wave_headers ) || ( !main_buffer ))
00145         return;
00146 
00147 
00148     //
00149     // This is the size for one buffer
00150     //
00151 
00152     DWORD buf_sz = mb_size / buffers;
00153 
00154 
00155 
00156     //
00157     // This is the base address for one buffer
00158     //
00159     
00160     BYTE * buf_addr = main_buffer;
00161 
00162 
00163     //
00164     // Initializes headers.
00165     //
00166 
00167     for ( unsigned int i = 0; i < buffers; ++i )
00168     {
00169         wave_headers[ i ].dwBufferLength = mb_size / buffers;
00170         wave_headers[ i ].lpData = ( LPSTR ) buf_addr;
00171 
00172         buf_addr += buf_sz;
00173     }
00174 
00175 }
00176 
00177 
00178 void 
00179 audio_wavein::prep_headers_( void )
00180 {
00181     MMRESULT err;
00182     bool error = false;
00183 
00184 
00185     //
00186     // If there is no memory for memory or
00187     // headers, throw error.
00188     //
00189 
00190     if (( !wave_headers ) 
00191         || ( !main_buffer ) || ( !wavein_handle ))
00192     {} //TODO: throw error!
00193 
00194 
00195 
00196     for ( unsigned int i = 0; i < buffers; ++i )
00197     {
00198         err = waveInPrepareHeader( wavein_handle, 
00199                     &wave_headers[ i ], sizeof( WAVEHDR ));
00200 
00201 
00202         if ( err != MMSYSERR_NOERROR )
00203             error = true;
00204 
00205     }
00206     
00207 
00208     if ( error )
00209         MessageBox( 0, TEXT("waveInPrepareHeader Error."), 0, 0 );
00210 
00211 
00212 
00213 }
00214 
00215 void 
00216 audio_wavein::unprep_headers_( void )
00217 {
00218     MMRESULT err;
00219     bool error = false;
00220 
00221 
00222 
00223     //
00224     // If there is no memory for memory or
00225     // headers, throw error.
00226     //
00227 
00228     if (( !wave_headers ) 
00229         || ( !main_buffer ) || ( !wavein_handle ))
00230     {} //TODO: throw error!
00231 
00232 
00233 
00234     for ( unsigned int i = 0; i < buffers; ++i )
00235     {
00236         err = waveInUnprepareHeader( wavein_handle, 
00237                     &wave_headers[ i ], sizeof( WAVEHDR ));
00238 
00239 
00240         if ( err != MMSYSERR_NOERROR )
00241             error = true;
00242 
00243     }
00244     
00245 
00246     if ( error )
00247         MessageBox( 0, TEXT("waveInUnPrepareHeader Error."), 0, 0 );
00248 
00249 }
00250 
00251 
00252 void 
00253 audio_wavein::add_buffers_to_driver_( void )
00254 {
00255     MMRESULT err;
00256     bool error = false;
00257 
00258 
00259 
00260     //
00261     // If there is no memory for memory or
00262     // headers, throw error.
00263     //
00264 
00265     if (( !wave_headers ) 
00266         || ( !main_buffer ) || ( !wavein_handle ))
00267     {} //TODO: throw error!
00268 
00269 
00270 
00271 
00272     for ( unsigned int i = 0; i < buffers; ++i )
00273     {
00274         err = waveInAddBuffer( wavein_handle, 
00275                 &wave_headers[ i ], sizeof( WAVEHDR ));
00276 
00277 
00278         if ( err != MMSYSERR_NOERROR )
00279             error = true;
00280 
00281     }
00282     
00283 
00284     if ( error )
00285         MessageBox( 0, TEXT("waveInAddBuffer Error."), 0, 0 );
00286 
00287 }
00288 
00289 
00290 
00291 void
00292 audio_wavein::close( void ) 
00293 {
00294 
00295 
00296 
00297 
00298     //
00299     // If wavein object is already in the status
00300     // NOTREADY, nothing to do. 
00301     //
00302 
00303     if ( status == WAVEIN_NOTREADY )
00304         return;
00305 
00306 
00307 
00308     //
00309     // If the wavein is recording,
00310     // then stop recording and close it.
00311     //
00312     
00313     if ( status == WAVEIN_RECORDING )
00314         stop_recording();
00315 
00316 
00317     //
00318     // Updating status.
00319     //
00320 
00321     status = WAVEIN_NOTREADY;
00322 
00323 
00324 
00325 
00326     //
00327     // Wakeing up recording thread, so it
00328     // can receive the `MM_WIM_CLOSE' message
00329     // then dies.
00330     //
00331     if ( wakeup_recthread )
00332         SetEvent( wakeup_recthread );
00333 
00334 
00335 
00336     //
00337     // Closing wavein stream
00338     //
00339 
00340     while (( waveInClose( wavein_handle )) 
00341                     != MMSYSERR_NOERROR ) Sleep( 1 );
00342 
00343 
00344 
00345     //
00346     // Release buffers memory.
00347     //
00348 
00349     free_buffers_mem_();
00350 
00351 
00352     //
00353     // Re-initialize variables to the
00354     // initial state.
00355     //
00356 
00357     init_();
00358     
00359 }
00360 
00361 
00362 void
00363 audio_wavein::open( void )
00364 {
00365 
00366     MMRESULT err;
00367     HANDLE recthread_handle = 0;
00368 
00369 
00370     //
00371     // Checkin the status of the object
00372     //
00373 
00374     if ( status != WAVEIN_NOTREADY )
00375     {} //TODO: throw error
00376 
00377 
00378 
00379     //
00380     // Creating the EVENT object that will be signaled
00381     // when the recording thread has to wake up.
00382     //
00383 
00384     wakeup_recthread = 
00385         CreateEvent( 0, FALSE, FALSE, 0 );
00386 
00387 
00388     data_flushed_event = 
00389         CreateEvent( 0, FALSE, FALSE, 0 );
00390 
00391 
00392 
00393     if (( !wakeup_recthread ) || ( !data_flushed_event ))
00394     {
00395 
00396 
00397         status = WAVEIN_ERR;
00398 
00399         MessageBox( 0, TEXT("Thread Error."), 0, 0 );
00400 
00401         //TODO: throw error
00402     }
00403 
00404 
00405 
00406     //
00407     // Inialize buffers for recording audio 
00408     // data from the wavein audio line.
00409     //
00410 
00411     alloc_buffers_mem_( buffers, buf_secs );
00412     init_headers_();
00413 
00414 
00415 
00416 
00417 
00418 
00419     //
00420     // Sound format that will be captured by wavein
00421     //
00422 
00423     wave_format.wFormatTag = WAVE_FORMAT_PCM;
00424 
00425     wave_format.nChannels = aud_info.channels();
00426     wave_format.nSamplesPerSec = aud_info.sample_rate();
00427     wave_format.wBitsPerSample = aud_info.bits();
00428     wave_format.nBlockAlign = aud_info.block_align();
00429     wave_format.nAvgBytesPerSec = aud_info.byte_rate();
00430 
00431 
00432 
00433     //
00434     // Creating the recording thread
00435     //
00436 
00437     recthread_handle = 
00438         CreateThread( NULL, 
00439                       0, 
00440                       audio_wavein::recording_procedure, 
00441                       ( PVOID ) this, 
00442                       0, 
00443                       &recthread_id 
00444             );
00445 
00446     
00447 
00448     //
00449     // Checking thread handle
00450     //
00451 
00452     if ( !recthread_handle )
00453     {
00454 
00455         //
00456         // Updating status
00457         //
00458 
00459         status = WAVEIN_ERR;
00460 
00461         MessageBox( 0, TEXT("Thread Error."), 0, 0 );
00462         //TODO: throw error
00463 
00464     }
00465 
00466 
00467     //
00468     // We don't need the thread handle anymore,
00469     // so we can close it from now. (We'll just
00470     // need the thread ID for the `waveInOpen' API)
00471     //
00472 
00473     CloseHandle( recthread_handle );
00474 
00475 
00476 
00477     //
00478     // Opening audio line wavein
00479     //
00480 
00481     err = waveInOpen( &wavein_handle, 
00482                       0, 
00483                       &wave_format, 
00484                       recthread_id, 
00485                       0, 
00486                       CALLBACK_THREAD 
00487             );
00488 
00489 
00490     if ( err != MMSYSERR_NOERROR ) 
00491     {
00492 
00493 
00494         //
00495         // Updating status
00496         //
00497 
00498         status = WAVEIN_ERR;
00499 
00500         if ( err == WAVERR_BADFORMAT )
00501             MessageBox( 0, TEXT("waveInOpen Error"), 0, 0 );
00502 
00503 
00504         //TODO: throw error
00505     }
00506 
00507 
00508     //
00509     // Update object status
00510     //
00511 
00512     status = WAVEIN_READY;
00513 
00514 
00515 
00516     //
00517     // Now `audio_wavein' object is ready
00518     // for audio recording!
00519     //
00520 }
00521 
00522 
00523 
00524 void
00525 audio_wavein::start_recording( void )
00526 {
00527 
00528     MMRESULT err;
00529     BOOL ev;
00530 
00531 
00532 
00533     if (( status != WAVEIN_READY ) 
00534                 && ( status != WAVEIN_STOP ))
00535     {} //TODO: throw error
00536 
00537 
00538 
00539 
00540     //
00541     // Updating to the recording status
00542     //
00543 
00544     status = WAVEIN_RECORDING;
00545 
00546 
00547 
00548 
00549     //
00550     // Let's prepare header of type WAVEHDR that
00551     // we will pass to the driver with our
00552     // audio informations, and buffer informations.
00553     //
00554     
00555     prep_headers_();
00556 
00557 
00558 
00559     //
00560     // The waveInAddBuffer function sends an input buffer 
00561     // to the given waveform-audio input device. 
00562     // When the buffer is filled, the application is notified.
00563     //
00564 
00565     add_buffers_to_driver_();
00566 
00567 
00568 
00569 
00570 
00571     //
00572     // Signaling event for waking up
00573     // the recorder thread.
00574     //
00575     
00576     ev = SetEvent( wakeup_recthread );
00577 
00578 
00579     if ( !ev ) 
00580     {
00581 
00582 
00583         MessageBox( 0, TEXT("Event Error."), 0, 0 );
00584 
00585     }
00586     
00587 
00588     //
00589     // Start recording
00590     //
00591 
00592     
00593     err = waveInStart( wavein_handle );
00594 
00595 
00596     if ( err != MMSYSERR_NOERROR )
00597     {
00598 
00599         //
00600         // Updating status
00601         //
00602 
00603         status = WAVEIN_ERR;
00604 
00605         MessageBox( 0, TEXT("waveInStart Error."), 0, 0 );
00606 
00607 
00608         //TODO: throw error
00609 
00610     }
00611 
00612 }
00613 
00614 
00615 
00616 void
00617 audio_wavein::stop_recording( void )
00618 {
00619         
00620 
00621     MMRESULT err;
00622 
00623     if ( status != WAVEIN_RECORDING )
00624         return;
00625 
00626 
00627     
00628     status = WAVEIN_FLUSHING;
00629 
00630 
00631     //
00632     // waveInReset will make all pending buffer as done.
00633     //
00634 
00635     err = waveInReset( wavein_handle );
00636 
00637 
00638     if ( err != MMSYSERR_NOERROR )
00639     {
00640 
00641         //TODO: throw error
00642 
00643         MessageBox( 0, TEXT("waveInReset Error."), 0, 0 );
00644 
00645 
00646 
00647     }
00648 
00649 
00650     if ( data_flushed_event )
00651         WaitForSingleObject(data_flushed_event, INFINITE);
00652 
00653 
00654 
00655     
00656 
00657 
00658     
00659     //
00660     // Stop recording.
00661     //
00662 
00663     err = waveInStop( wavein_handle );
00664 
00665 
00666     if ( err != MMSYSERR_NOERROR )
00667     {
00668 
00669         //TODO: throw error
00670 
00671         MessageBox( 0, TEXT("waveInStop Error."), 0, 0 );
00672 
00673 
00674 
00675     }
00676 
00677 
00678     //
00679     // The waveInUnprepareHeader function cleans up the 
00680     // preparation performed by the waveInPrepareHeader function. 
00681     //
00682 
00683     unprep_headers_();
00684 
00685 
00686 
00687 
00688 
00689     
00690 
00691 
00692 
00693 
00694 
00695     status = WAVEIN_STOP;
00696 
00697 }
00698 
00699 
00700 
00701 DWORD WINAPI 
00702 audio_wavein::recording_procedure( LPVOID arg )
00703 {
00704 
00705 
00706     MSG msg;
00707     WAVEHDR * phdr;
00708     audio_wavein * _this = ( audio_wavein * ) arg;
00709 
00710     
00711 
00712 
00713     //
00714     // Check the arg pointer
00715     //
00716 
00717     if ( _this == 0 )
00718         return 0;
00719 
00720     
00721     
00722     //
00723     // The thread can go to sleep for now.
00724     // It will be wake up only when there is audio data
00725     // to be recorded.
00726     //
00727 
00728     if ( _this->wakeup_recthread )
00729         WaitForSingleObject(_this->wakeup_recthread, INFINITE);
00730 
00731 
00732 
00733 
00734 
00735     
00736     //
00737     // If status of the `audio_wavein' object 
00738     // is not ready or recording the thread can exit.
00739     //
00740 
00741     if (( _this->status != WAVEIN_READY ) && 
00742                 ( _this->status != WAVEIN_RECORDING ))
00743         return 0;
00744 
00745 
00746     
00747 
00748 
00749 
00750 
00751     //
00752     // Entering main polling loop
00753     //
00754 
00755     while ( GetMessage( &msg, 0, 0, 0 ))    
00756     {   
00757 
00758         switch ( msg.message )
00759         {
00760                 
00761             case MM_WIM_DATA:
00762             
00763                 phdr = ( WAVEHDR * ) msg.lParam;
00764 
00765                 if (( _this->status == WAVEIN_RECORDING ) 
00766                             || ( _this->status == WAVEIN_FLUSHING ))
00767                 {
00768 
00769 
00770                     if ( phdr->dwFlags & WHDR_DONE )
00771                     {
00772 
00773                         //
00774                         // Flushes recorded audio data to 
00775                         // the `audio_receiver' object.
00776                         //
00777 
00778                         _this->audio_rcvd.audio_receive(
00779                                 ( unsigned char * )phdr->lpData, 
00780                                 phdr->dwBytesRecorded 
00781                             );
00782 
00783                         
00784                         //
00785                         // Updating `audio_receiver' total
00786                         // bytes received _AFTER_ calling
00787                         // `audio_receive' function.
00788                         //
00789 
00790                         _this->audio_rcvd.bytes_received += 
00791                                         phdr->dwBytesRecorded;
00792                     }
00793     
00794 
00795                             
00796                     //
00797                     // If status is not flushing data, then
00798                     // we can re-add the buffer for reusing it.
00799                     // Otherwise, if we are flushing pending data,
00800                     // we cannot re-add buffer because we don't need
00801                     // it anymore
00802                     //
00803 
00804                     if ( _this->status != WAVEIN_FLUSHING )
00805                     {
00806 
00807                         //
00808                         // Let the audio driver reuse the buffer
00809                         //
00810 
00811                         waveInAddBuffer( _this->wavein_handle, 
00812                                             phdr, sizeof( WAVEHDR ));
00813 
00814 
00815                     } else {
00816 
00817                         //
00818                         // If we are flushing pending data, we have
00819                         // to prepare to stop recording.
00820                         // Set WAVEHDR flag to 0, and fires the event
00821                         // `data_flushed_event', that will wake up
00822                         // the main thread that is sleeping into
00823                         // wavein_in::stop_recording() member function,
00824                         // waiting the last `MM_WIM_DATA' message that
00825                         // contain pending data.
00826                         //
00827 
00828                         phdr->dwFlags = 0;
00829 
00830                         SetEvent( _this->data_flushed_event );
00831 
00832 
00833                         //
00834                         // The recording is gooing to stop, so the
00835                         // recording thread can go to sleep!
00836                         //
00837 
00838                         WaitForSingleObject(_this->wakeup_recthread, INFINITE);
00839 
00840                     }
00841 
00842 
00843                 }//if WAVEIN_RECORDING || WAVEIN_FLUSHING
00844 
00845                 break;
00846 
00847 
00848             
00849 
00850                         
00851 
00852 
00853 
00854 
00855             case MM_WIM_CLOSE:
00856 
00857                 //
00858                 // The thread can exit now.
00859                 //
00860 
00861                 return 0;
00862 
00863                 break;
00864 
00865 
00866 
00867         }  //end switch( msg.message )
00868         
00869     }  //end while( GetMessage( ... ))
00870 
00871     return 0;               
00872 }
00873 
00874 
00875 
00876 
00877 
00878 
00879 _AUDIO_NAMESPACE_END_

Generated on Sat May 26 2012 04:16:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.