--- /dev/null
+#ifndef _AUDIO_DEF__H_
+#define _AUDIO_DEF__H_
+
+
+#include <iostream>
+
+//
+// Defaults
+//
+
+#define _AUDIO_DEFAULT_FORMAT A44100_16BIT_STEREO
+#define _AUDIO_DEFAULT_WAVEINBUFFERS 8
+#define _AUDIO_DEFAULT_WAVEINBUFSECS 0.1f
+#define _AUDIO_DEFAULT_WAVEOUTBUFFERS 8
+#define _AUDIO_DEFAULT_WAVEOUTBUFSECS 0.1f
+#define _AUDIO_DEFAULT_BUFSECS 1.0f
+
+
+//
+// Namespace stuff
+//
+
+#define _AUDIO_NAMESPACE_START_ namespace snd {
+#define _AUDIO_NAMESPACE_END_ };
+//
+// Platform depend stuff
+//
+
+#include <windows.h>
+#include <mmsystem.h> //Windows MultiMedia (WINMM) audio apis
+#include <mmreg.h> //codecs stuff
+#include <Msacm.h> //codecs stuff
+
+#endif //ifdef _AUDIO_DEF__H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_format.cpp
+ * PURPOSE: Audio Format
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+
+#include "stdafx.h"
+#include "audio_format.hpp"
+
+_AUDIO_NAMESPACE_START_
+
+//
+// Standard audio formats (declared as
+// externs in `audio_format.hpp')
+//
+
+audio_format UNNKOWN_FORMAT( 0, 0, 0);
+audio_format A44100_16BIT_STEREO( 44100, 16, 2 );
+
+_AUDIO_NAMESPACE_END_
+
--- /dev/null
+#ifndef _AUDIOFORMAT__H_
+#define _AUDIOFORMAT__H_
+
+
+
+#include "audio_def.hpp"
+
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+
+
+
+
+class audio_format
+{
+ protected:
+
+
+ unsigned int samples_psec;
+ unsigned short int bits_psample;
+ unsigned short int chan;
+
+
+ public:
+
+
+ //
+ // Ctors
+ //
+
+ audio_format( unsigned int samples_per_second,
+ unsigned short int bits_per_sample, unsigned short int channels )
+
+ : samples_psec( samples_per_second ), bits_psample( bits_per_sample ),
+ chan( channels )
+
+ { }
+
+
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ virtual ~audio_format( void )
+ { }
+
+
+
+
+
+
+
+ //
+ // Operators
+ //
+
+ bool operator==( audio_format & eq ) const
+ {
+ //
+ // The same audio format is when samples per second,
+ // bit per sample, and channels mono/stereo are equal.
+ //
+
+ return (( samples_psec == eq.samples_psec )
+ && ( bits_psample == eq.bits_psample ) && ( chan == eq.chan ));
+ }
+
+
+
+
+
+
+
+
+ //
+ // Public Functions
+ //
+
+ unsigned int sample_rate( void ) const
+ { return samples_psec; }
+
+
+ unsigned short int bits( void ) const
+ { return bits_psample; }
+
+
+ unsigned short int channels( void ) const
+ { return chan; }
+
+
+ unsigned int byte_rate( void ) const
+ { return ( samples_psec * chan * ( bits_psample / 8 )); }
+
+
+ unsigned int block_align( void ) const
+ { return ( chan * ( bits_psample / 8 )); }
+
+
+
+ unsigned int samples_in_seconds( float seconds ) const
+ {
+
+ return ( unsigned int )
+ ((( float )samples_psec * ( float ) chan ) * seconds );
+
+ }
+
+ unsigned int samples_in_bytes ( unsigned int bytes ) const
+ {
+
+ return ( bytes / (( bits_psample / 8 ) * chan ));
+
+ }
+
+};
+
+
+
+
+extern audio_format UNKNOWN_FORMAT;
+extern audio_format A44100_16BIT_STEREO;
+
+
+
+
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+
+
+
+#endif //ifdef _AUDIOFORMAT__H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_membuffer.cpp
+ * PURPOSE: Audio MemBuffer
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+#include "stdafx.h"
+#include "audio_membuffer.hpp"
+
+_AUDIO_NAMESPACE_START_
+
+
+void
+ audio_membuffer::alloc_mem_( unsigned int bytes )
+{
+
+ //
+ // Some checking
+ //
+
+ if ( bytes == 0 )
+ return;
+
+
+
+
+
+ //
+ // Checks previsiously alloc'd memory
+ // and frees it.
+ //
+
+ if ( audio_data )
+ delete[] audio_data;
+
+
+
+ //
+ // Allocs new memory and zeros it.
+ //
+
+ audio_data = new BYTE[ bytes ];
+
+
+ memset( audio_data, 0, bytes * sizeof( BYTE ));
+
+
+
+ //
+ // Sets the correct buffer size
+ //
+
+ buf_size = bytes;
+
+
+ init_size = bytes;
+
+
+
+}
+
+
+void
+ audio_membuffer::free_mem_( void )
+{
+
+ if ( audio_data )
+ delete[] audio_data;
+
+ buf_size = 0;
+ audio_data = 0;
+
+}
+
+
+void
+ audio_membuffer::resize_mem_( unsigned int new_size )
+{
+
+
+ if ( new_size == 0 )
+ return;
+
+
+ //
+ // The new_size, cannot be <= of the
+ // `bytes_received' member value of the
+ // parent class `audio_receiver'.
+ // We cannot touch received audio data,
+ // so we have to alloc at least
+ // bytes_received+1 bytes.
+ //
+ // But we can truncate unused memory, so
+ // `new_size' can be < of `buf_size'.
+ //
+
+ if ( new_size <= bytes_received )
+ return;
+
+
+
+
+ BYTE * new_mem;
+
+
+
+ //
+ // Allocs new memory and zeros it.
+ //
+
+
+ new_mem = new BYTE[ new_size ];
+
+ memset( new_mem, 0, new_size * sizeof( BYTE ));
+
+
+
+ if ( audio_data )
+ {
+
+
+ //
+ // Copies received audio data, and discard
+ // unused memory.
+ //
+
+ memcpy( new_mem, audio_data, bytes_received );
+
+
+
+ //
+ // Frees old memory.
+ //
+
+ delete[] audio_data;
+
+
+
+
+
+ //
+ // Commit new memory.
+ //
+
+ audio_data = new_mem;
+ buf_size = new_size;
+
+
+
+
+ } else {
+
+ audio_data = new_mem;
+ buf_size = new_size;
+ }
+
+
+ if ( buffer_resized )
+ buffer_resized( new_size );
+
+}
+
+
+
+
+void
+ audio_membuffer::truncate_( void )
+{
+
+ //
+ // If `buf_size' is already = to the
+ // `bytes_received' of audio data, then
+ // this operation is useless; simply return.
+ //
+
+ if ( bytes_received == buf_size )
+ return;
+
+
+
+ if ( audio_data )
+ {
+
+
+ //
+ // Allocs a new buffer.
+ //
+
+ BYTE * newbuf = new BYTE[ bytes_received ];
+
+
+
+
+ //
+ // Copies audio data.
+ //
+
+ memcpy( newbuf, audio_data, bytes_received );
+
+
+
+ //
+ // Frees old memory.
+ //
+
+ delete[] audio_data;
+
+
+
+ //
+ // Commit the new buffer.
+ //
+
+ audio_data = newbuf;
+ buf_size = bytes_received;
+
+
+
+ //
+ // Buffer truncation successfull.
+ // Now the buffer size is exactly big
+ // as much audio data was received.
+ //
+
+
+ }
+
+
+}
+
+
+
+
+
+
+//////////////////////////////////////
+/////// Public Functions ///////////
+//////////////////////////////////////
+
+
+
+
+void
+ audio_membuffer::clear( void )
+{
+
+ free_mem_();
+
+ bytes_received = 0;
+}
+
+
+
+void
+ audio_membuffer::reset( void )
+{
+
+
+ //
+ // Frees memory and reset
+ // to initial state.
+ //
+
+ clear();
+
+
+
+ //
+ // Alloc memory of size specified
+ // at the constructor.
+ //
+
+ alloc_mem_( init_size );
+
+
+}
+
+void
+ audio_membuffer::alloc_bytes( unsigned int bytes )
+{
+
+ alloc_mem_( bytes );
+
+}
+
+
+
+
+void
+ audio_membuffer::alloc_seconds( unsigned int secs )
+{
+
+ alloc_mem_( aud_info.byte_rate() * secs );
+
+}
+
+
+void
+ audio_membuffer::alloc_seconds( float secs )
+{
+
+ alloc_mem_(( unsigned int )(( float ) aud_info.byte_rate() * secs ));
+
+}
+
+
+
+
+void
+ audio_membuffer::resize_bytes( unsigned int bytes )
+{
+
+ resize_mem_( bytes );
+
+}
+
+
+
+void
+ audio_membuffer::resize_seconds( unsigned int secs )
+{
+
+ resize_mem_( aud_info.byte_rate() * secs );
+
+}
+
+
+void
+ audio_membuffer::resize_seconds( float secs )
+{
+
+ resize_mem_(( unsigned int )
+ (( float )aud_info.byte_rate() * secs )
+ );
+
+}
+
+
+
+
+
+
+///////////////////////////////////////
+/////// Inherited Functions /////////
+///////////////////////////////////////
+
+
+
+
+
+
+
+void
+ audio_membuffer::audio_receive
+ ( unsigned char * data, unsigned int size )
+{
+
+
+ //
+ // If there isn't a buffer, allocs memory for
+ // it of size*2, and copies audio data arrival.
+ //
+
+ if (( audio_data == 0 ) || ( buf_size == 0 ))
+ {
+ alloc_mem_( size * 2 );
+
+ memcpy( audio_data, data, size );
+
+ return;
+
+ }
+
+
+
+
+
+ //
+ // If buffer's free memory is < of `size',
+ // we have to realloc buffer memory of
+ // buf_size*2, while free memory is enough
+ // to contain `size' bytes.
+ //
+ // In this case free memory is represented
+ // by `buf_size - bytes_recorded'.
+ //
+
+ unsigned int tot_mem = buf_size,
+ free_mem = buf_size - bytes_received;
+
+
+ if ( free_mem < size )
+ {
+
+ //
+ // Calcs new buffer size.
+ // TODO: flags for other behaviour?
+
+ while ( free_mem < size )
+ {
+ tot_mem *= 2;
+
+ free_mem = tot_mem - bytes_received;
+ }
+
+
+
+ //
+ // Resize buffer memory.
+ //
+
+ resize_mem_( tot_mem );
+
+ }
+
+
+ //
+ // Now we have enough free space in the
+ // buffer, so let's copy audio data arrivals.
+ //
+
+ memcpy( audio_data + bytes_received, data, size );
+
+
+
+
+ if ( audio_arrival )
+ audio_arrival( aud_info.samples_in_bytes( size ));
+
+
+
+}
+
+
+unsigned int
+ audio_membuffer::read( BYTE * out_buf, unsigned int bytes )
+{
+
+ //
+ // Some checking
+ //
+
+ if ( !audio_data )
+ return 0;
+
+
+ if ( bytes_played_ >= bytes_received )
+ return 0;
+
+
+
+ unsigned int to_play =
+ bytes_received - bytes_played_;
+
+
+ unsigned int to_copy =
+ bytes > to_play ? to_play : bytes;
+
+
+ //
+ // Copies the audio data out.
+ //
+
+ if (( out_buf ) && ( to_copy ) && ( audio_data ))
+ memcpy( out_buf, audio_data + bytes_played_, to_copy );
+
+
+ //
+ // Increments the number of total bytes
+ // played (audio data gone out from the
+ // `audio_producer' object).
+ //
+
+ bytes_played_ += bytes;
+
+
+ if ( audio_arrival )
+ audio_arrival( aud_info.samples_in_bytes( bytes ));
+
+
+ //
+ // Returns the exact size of audio data
+ // produced.
+ //
+
+ return to_copy;
+}
+
+
+bool
+ audio_membuffer::finished( void )
+{
+ if ( bytes_played_ < bytes_received )
+ return false;
+ else
+ return true;
+}
+
+_AUDIO_NAMESPACE_END_
--- /dev/null
+#ifndef _AUDIOMEMBUFFER__H_
+#define _AUDIOMEMBUFFER__H_
+
+
+
+#include "audio_def.hpp"
+#include "audio_receiver.hpp"
+#include "audio_format.hpp"
+#include "audio_producer.hpp"
+
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+class audio_membuffer : public audio_receiver, public audio_producer
+{
+
+
+
+
+
+ protected:
+
+ BYTE * audio_data;
+ audio_format aud_info;
+ unsigned int buf_size;
+ unsigned int init_size;
+
+
+
+ //
+ // Protected Functions
+ //
+
+
+ //allocs N bytes for the audio buffer.
+ void alloc_mem_( unsigned int );
+
+
+ //frees memory
+ void free_mem_( void );
+
+
+ //resizes memory, and copies old
+ //audio data to new-size memory
+ void resize_mem_( unsigned int );
+
+
+ //truncates and discards unused memory.
+ //`buf_size' will be the same as `bytes_received'.
+ void truncate_( void );
+
+
+
+
+ public:
+
+
+ void ( * audio_arrival )( unsigned int );
+ void ( * buffer_resized ) ( unsigned int );
+
+
+ //
+ // Ctors
+ //
+
+ audio_membuffer( void )
+ : audio_data( 0 ), aud_info( _AUDIO_DEFAULT_FORMAT ),
+ buf_size( 0 ), init_size( 0 )
+ {
+
+ //
+ // Allocs memory for at least 1 or some seconds
+ // of recording.
+ //
+ init_size = ( unsigned int )
+ (( float )aud_info.byte_rate() * _AUDIO_DEFAULT_BUFSECS );
+
+
+ alloc_mem_( init_size );
+
+
+ }
+
+
+
+ audio_membuffer( audio_format aud_fmt )
+ : audio_data( 0 ), aud_info( aud_fmt ), buf_size( 0 ),
+ init_size( 0 )
+ {
+
+ //
+ // Allocs memory for at least 1 or some seconds
+ // of recording.
+ //
+ init_size = ( unsigned int )
+ (( float )aud_info.byte_rate() * _AUDIO_DEFAULT_BUFSECS );
+
+
+ alloc_mem_( init_size );
+
+ }
+
+
+
+
+ audio_membuffer( audio_format aud_fmt, unsigned int seconds )
+ : audio_data( 0 ), aud_info( aud_fmt ), buf_size( 0 ),
+ init_size( 0 )
+ {
+
+ //
+ // Allocs memory for audio recording
+ // the specified number of seconds.
+ //
+ init_size = aud_info.byte_rate() * seconds;
+ alloc_mem_( init_size );
+
+ }
+
+
+
+ audio_membuffer( audio_format aud_fmt, float seconds )
+ : audio_data( 0 ), aud_info( aud_fmt ), buf_size( 0 ),
+ init_size( 0 )
+ {
+
+ //
+ // Allocs memory for audio recording
+ // the specified number of seconds.
+ //
+ init_size = ( unsigned int )(( float ) aud_info.byte_rate() *
+ seconds <= 0 ? 1 : seconds );
+
+
+ alloc_mem_( init_size );
+
+ }
+
+
+
+
+ audio_membuffer( unsigned int bytes )
+ : audio_data( 0 ), aud_info( _AUDIO_DEFAULT_FORMAT ),
+ buf_size( 0 ), init_size( 0 )
+ {
+
+ //
+ // Allocs memory for the specified bytes
+ //
+ init_size = bytes;
+ alloc_mem_( init_size );
+
+ }
+
+
+
+
+ //
+ // Dtor
+ //
+
+ virtual ~audio_membuffer( void )
+ {
+
+ //
+ // Frees memory and reset values.
+ //
+
+ clear();
+
+ }
+
+
+
+
+
+
+
+
+
+ //
+ // Public functions
+ //
+
+
+
+ //returns the audio buffer size in bytes.
+ unsigned int mem_size( void ) const
+ { return buf_size; }
+
+
+ //returns how many audio data has been
+ //received, in bytes.
+ unsigned int bytes_recorded( void ) const
+ { return bytes_received; }
+
+
+ //returns the integer number of seconds
+ //that the buffer can record
+ unsigned int seconds_total( void ) const
+ { return buf_size / aud_info.byte_rate(); }
+
+
+ //returns the integer number of seconds
+ //that the buffer can record
+ unsigned int seconds_recorded( void ) const
+ { return bytes_received / aud_info.byte_rate(); }
+
+
+ //returns the float number of seconds
+ //that the buffer can record
+ float fseconds_total( void ) const
+ { return ( float )(( float ) buf_size /
+ ( float ) aud_info.byte_rate()); }
+
+
+ //returns the float number of seconds
+ //that has been recorded
+ float fseconds_recorded( void ) const
+ { return ( float )(( float ) bytes_received /
+ ( float ) aud_info.byte_rate()); }
+
+
+ unsigned int total_samples( void ) const
+ {
+
+ return ( aud_info.samples_in_seconds( fseconds_total() ));
+
+ }
+
+
+ unsigned int samples_received( void ) const
+ {
+
+
+ return ( aud_info.samples_in_bytes( bytes_received ));
+
+ }
+
+
+
+ //returns a pointer to the audio buffer
+ BYTE * audio_buffer( void ) const
+ { return audio_data; }
+
+
+
+ //frees memory and resets values.
+ void clear( void );
+
+
+ audio_format & audinfo( void ) { return aud_info; }
+
+
+ //discard audio data, resets values,
+ //but, instead of clear() which frees memory,
+ //reset the memory to the initial size, ready
+ //for receiving "new" audio data.
+ void reset( void );
+
+
+ //truncates and discards unused memory.
+ //`buf_size' will be the same as `bytes_received'.
+ void truncate( void )
+ { truncate_( ); }//TODO: fare truncate N bytes
+
+
+ //if there is a buffer, discards current buffer
+ //memory and realloc a new memory buffer with a
+ //new size expressed in bytes.
+ void alloc_bytes( unsigned int );
+
+
+
+ //if there is a buffer, discards current buffer
+ //memory and realloc a new memory buffer with a
+ //new size expressed in seconds, integer and float.
+ void alloc_seconds( unsigned int );
+ void alloc_seconds( float );
+
+
+
+ //resizes in bytes the current buffer,
+ //without discarding previsiously audio data received.
+ void resize_bytes( unsigned int );
+
+
+ //resizes in seconds the current buffer,
+ //without discarding previsiously audio data received.
+ void resize_seconds( unsigned int );
+ void resize_seconds( float );
+
+
+
+
+
+
+
+
+
+ //
+ // Inherited Functions from `audio_receiver'
+ //
+
+ void audio_receive( unsigned char *, unsigned int );
+
+
+
+
+ //
+ // Inherited Functions from `audio_buffer'
+ //
+
+
+ unsigned int read( BYTE *, unsigned int );
+ bool finished( void );
+
+
+
+};
+
+
+
+
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+
+#endif //ifdef _AUDIOMEMBUFFER__H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_producer.cpp
+ * PURPOSE: Audio Format
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+
+#include "StdAfx.h"
+#include "audio_producer.hpp"
+
--- /dev/null
+#ifndef _AUDIOAUDBUF__H_
+#define _AUDIOAUDBUF__H_
+
+
+
+#include "audio_def.hpp"
+
+
+_AUDIO_NAMESPACE_START_
+
+
+class audio_producer
+{
+
+
+ protected:
+
+
+ unsigned int bytes_played_;
+
+
+
+
+
+ public:
+
+
+ //
+ // Ctors
+ //
+
+ audio_producer ( ) : bytes_played_( 0 )
+ { }
+
+
+
+
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ virtual ~audio_producer( void )
+ { }
+
+
+
+
+ //
+ // Public Functions
+ //
+
+
+ //reads N bytes from the buffer
+ virtual unsigned int read( BYTE *, unsigned int ) = 0;
+
+ virtual bool finished ( void ) = 0;
+
+
+
+
+ unsigned int bytes_played( void ) const
+ {
+ return bytes_played_;
+ }
+
+
+ void set_position( unsigned int pos )
+ {
+ bytes_played_ = pos;
+ }
+
+ void set_position_start( void )
+ {
+ bytes_played_ = 0 ;
+ }
+
+
+
+ void forward( unsigned int bytes )
+ {
+ bytes_played_ += bytes ;
+ }
+
+
+ void backward( unsigned int bytes )
+ {
+ bytes_played_ += bytes ;
+ }
+
+ void ( * play_finished )( void );
+
+
+
+
+};
+
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+
+
+#endif //ifdef _AUDIOAUDBUF__H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_producer.cpp
+ * PURPOSE: Audio Format
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+#include "stdafx.h"
+#include "audio_receiver.hpp"
+
+
+
+
+_AUDIO_NAMESPACE_START_
+
+_AUDIO_NAMESPACE_END_
--- /dev/null
+#ifndef _AUDIORECEIVER_DEF__H_
+#define _AUDIORECEIVER_DEF__H_
+
+
+
+#include "audio_def.hpp"
+
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+
+//TODO: differenziare audio_receiver da audio_sink?
+//TODO: creare un audio_receiver Tee
+
+
+
+
+
+class audio_receiver
+{
+
+ //
+ // The `audio_wavein' class, while is
+ // recording audio, has to access to
+ // protected members of `audio_receiver'
+ // such as `bytes_received' protected
+ // variable.
+ //
+
+ friend class audio_wavein;
+
+
+
+
+
+
+ protected:
+
+
+ unsigned int bytes_received;
+ unsigned int status;
+
+
+
+ public:
+
+
+ //
+ // Ctors
+ //
+
+ audio_receiver( void )
+ : bytes_received( 0 )
+ { }
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ virtual ~audio_receiver( void )
+ { }
+
+
+
+
+ //
+ // Public Functions
+ //
+
+ virtual void audio_receive( unsigned char *, unsigned int ) = 0;
+
+ //virtual void start_rec( void ) = 0;
+ //virtual void stop_rec( void ) = 0;
+
+
+
+ void set_b_received( unsigned int r )
+ { bytes_received = r; }
+};
+
+
+
+
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+
+
+
+#endif //ifdef _AUDIORECEIVER_DEF__H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_resampler_acm.cpp
+ * PURPOSE: Audio Resampler
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+#include "stdafx.h"
+#include "audio_resampler_acm.hpp"
+
+_AUDIO_NAMESPACE_START_
+
+
+ /////////////////////////////////////////
+ /////// Private Functions ////////
+ /////////////////////////////////////////
+
+
+ void
+ audio_resampler_acm::init_( void )
+{
+
+
+
+ //
+ // Zeroing structures
+ //
+
+ ZeroMemory( &acm_header, sizeof( ACMSTREAMHEADER ));
+ ZeroMemory( &wformat_src, sizeof( WAVEFORMATEX ));
+ ZeroMemory( &wformat_dst, sizeof( WAVEFORMATEX ));
+
+
+
+
+ //
+ // Setting structures sizes
+ //
+
+ acm_header.cbStruct = sizeof( ACMSTREAMHEADER );
+ wformat_src.cbSize = sizeof( WAVEFORMATEX );
+ wformat_dst.cbSize = sizeof( WAVEFORMATEX );
+
+
+
+
+ //
+ // Setting WAVEFORMATEX structure parameters
+ // according to `audio_format' in/out classes
+ //
+
+ wformat_src.wFormatTag = WAVE_FORMAT_PCM;
+ wformat_src.nSamplesPerSec = audfmt_in.sample_rate();
+ wformat_src.nChannels = audfmt_in.channels();
+ wformat_src.wBitsPerSample = audfmt_in.bits();
+ wformat_src.nAvgBytesPerSec = audfmt_in.byte_rate();
+ wformat_src.nBlockAlign = audfmt_in.block_align();
+
+
+ wformat_dst.wFormatTag = WAVE_FORMAT_PCM;
+ wformat_dst.nSamplesPerSec = audfmt_out.sample_rate();
+ wformat_dst.nChannels = audfmt_out.channels();
+ wformat_dst.wBitsPerSample = audfmt_out.bits();
+ wformat_dst.nAvgBytesPerSec = audfmt_out.byte_rate();
+ wformat_dst.nBlockAlign = audfmt_out.block_align();
+
+
+
+ //
+ // Init acm structures completed successfull
+ //
+}
+
+
+
+
+
+
+
+
+
+
+
+/////////////////////////////////////////
+/////// Public Functions ////////
+/////////////////////////////////////////
+
+
+
+
+void
+ audio_resampler_acm::open( void )
+{
+
+
+ MMRESULT err;
+
+
+ //
+ // Opens ACM stream
+ //
+
+ err = acmStreamOpen( &acm_stream, 0, &wformat_src, &wformat_dst,
+ 0, 0, 0, ACM_STREAMOPENF_NONREALTIME );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ //TODO: throw error
+ printf("acmOpen error: %i\n", err);
+
+ }
+
+
+
+ //
+ // Calcs source buffer lenght
+ //
+
+ src_buflen = ( unsigned int )
+ (( float )audfmt_in.byte_rate() * ( float )buf_secs );
+
+
+
+
+
+
+ //
+ // Calcs destination source buffer lenght
+ // with help of ACM apis
+ //
+
+ err = acmStreamSize( acm_stream,
+ src_buflen, &dst_buflen, ACM_STREAMSIZEF_SOURCE );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ //TODO: throw error
+ printf("acmSize error\n");
+
+ }
+
+
+
+ //
+ // Initialize ACMSTREAMHEADER structure,
+ // and alloc memory for source and destination
+ // buffers.
+ //
+
+ acm_header.fdwStatus = 0;
+ acm_header.dwUser = 0;
+
+
+ acm_header.pbSrc = ( LPBYTE ) new BYTE [ src_buflen ];
+ acm_header.cbSrcLength = src_buflen;
+ acm_header.cbSrcLengthUsed = 0;
+ acm_header.dwSrcUser = src_buflen;
+
+
+ acm_header.pbDst = ( LPBYTE ) new BYTE [ dst_buflen ];
+ acm_header.cbDstLength = dst_buflen;
+ acm_header.cbDstLengthUsed = 0;
+ acm_header.dwDstUser = dst_buflen;
+
+
+
+
+ //
+ // Give ACMSTREAMHEADER initialized correctly to the
+ // driver.
+ //
+
+ err = acmStreamPrepareHeader( acm_stream, &acm_header, 0L );
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ //TODO: throw error
+ printf("prep. header error\n");
+ }
+
+
+
+
+ //
+ // ACM stream successfully opened.
+ //
+
+ stream_opened = true;
+
+}
+
+
+
+
+void
+ audio_resampler_acm::close( void )
+{
+
+
+ MMRESULT err;
+
+
+ if ( acm_stream )
+ {
+
+ if ( acm_header.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED )
+ {
+
+ acm_header.cbSrcLength = src_buflen;
+ acm_header.cbDstLength = dst_buflen;
+
+ err = acmStreamUnprepareHeader( acm_stream, &acm_header, 0L );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ //
+ // Free buffer memory
+ //
+
+ if ( acm_header.pbSrc != 0 )
+ delete[] acm_header.pbSrc;
+
+ if ( acm_header.pbDst != 0 )
+ delete[] acm_header.pbDst;
+
+
+ //
+ // Re-init structures
+ //
+
+ init_();
+
+ //
+ // Updating status
+ //
+
+ stream_opened = false;
+
+
+ //TODO: throw error
+
+ }
+ }
+
+
+ err = acmStreamClose( acm_stream, 0 );
+ acm_stream = 0;
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ //
+ // Free buffer memory
+ //
+
+ if ( acm_header.pbSrc != 0 )
+ delete[] acm_header.pbSrc;
+
+ if ( acm_header.pbDst != 0 )
+ delete[] acm_header.pbDst;
+
+
+ //
+ // Re-init structures
+ //
+
+ init_();
+
+
+ //
+ // Updating status
+ //
+
+ stream_opened = false;
+
+
+ //TODO: throw error!
+
+ }
+
+
+ }//if acm_stream != 0
+
+
+
+
+
+
+ //
+ // Free buffer memory
+ //
+
+ if ( acm_header.pbSrc != 0 )
+ delete[] acm_header.pbSrc;
+
+ if ( acm_header.pbDst != 0 )
+ delete[] acm_header.pbDst;
+
+
+ //
+ // Re-init structures
+ //
+
+ init_();
+
+
+ //
+ // Updating status
+ //
+
+ stream_opened = false;
+
+
+
+ //
+ // ACM sream successfully closed.
+ //
+
+
+}
+
+
+
+
+void
+ audio_resampler_acm::audio_receive( unsigned char * data, unsigned int size )
+{
+
+ MMRESULT err;
+
+ //
+ // Checking for acm stream opened
+ //
+
+ if ( stream_opened )
+ {
+
+
+ //
+ // Copy audio data from extern to
+ // internal source buffer
+ //
+
+ memcpy( acm_header.pbSrc, data, size );
+
+
+ acm_header.cbSrcLength = size;
+ acm_header.cbDstLengthUsed = 0;
+
+ err = acmStreamConvert( acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN );
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ //TODO: throw error
+ printf("acm convert error\n");
+
+ }
+
+
+ //
+ // Wait for sound conversion
+ //
+
+ while(( ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus ) == 0 );
+
+
+ printf("Processed successfully %lu bytes of audio.\n", acm_header.cbDstLengthUsed );
+
+
+
+ //
+ // Copy resampled audio, to destination buffer.
+ //
+
+ //memcpy( pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed );
+
+
+ }
+
+}
+
+_AUDIO_NAMESPACE_END_
--- /dev/null
+#ifndef _AUDIORESAMPLERACM__H_
+#define _AUDIORESAMPLERACM__H_
+
+
+
+#include "audio_def.hpp"
+#include "audio_receiver.hpp"
+#include "audio_format.hpp"
+
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+//TODO: inherit from a base resampler?
+class audio_resampler_acm : public audio_receiver
+{
+
+ private:
+ void init_( void );
+
+
+ protected:
+
+
+ HACMSTREAM acm_stream;
+ ACMSTREAMHEADER acm_header;
+ DWORD src_buflen;
+ DWORD dst_buflen;
+ bool stream_opened;
+
+ audio_format audfmt_in;
+ audio_format audfmt_out;
+
+ float buf_secs;
+
+ WAVEFORMATEX wformat_src;
+ WAVEFORMATEX wformat_dst;
+
+
+
+
+ public:
+
+
+ //
+ // Ctors
+ //
+
+ audio_resampler_acm( audio_format fmt_in, audio_format fmt_out )
+ : acm_stream( 0 ), src_buflen( 0 ), dst_buflen( 0 ),
+ stream_opened( false ), audfmt_in( fmt_in ), audfmt_out( fmt_out ),
+ buf_secs( _AUDIO_DEFAULT_BUFSECS )
+
+ {
+
+
+ init_();
+
+
+ }
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ ~audio_resampler_acm( void )
+ { }
+
+
+
+ //
+ // Public functions
+ //
+
+ void open( void );
+ void close( void );
+
+
+
+ void audio_receive( unsigned char *, unsigned int );
+
+
+
+};
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+#endif //ifdef _AUDIORESAMPLERACM_H_
--- /dev/null
+/*
+* PROJECT: ReactOS Sound Record Application
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: base/applications/sndrec32/audio_wavein.cpp
+* PURPOSE: Audio WaveIn
+* PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+*/
+
+#include "stdafx.h"
+#include "audio_wavein.hpp"
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+ void
+ audio_wavein::init_( void )
+{
+ ZeroMemory(( LPVOID ) &wave_format,
+ sizeof( WAVEFORMATEX ));
+
+ wave_format.cbSize = sizeof( WAVEFORMATEX );
+
+ wavein_handle = 0;
+ recthread_id = 0;
+ wakeup_recthread = 0;
+
+ buf_secs = _AUDIO_DEFAULT_WAVEINBUFSECS;
+
+
+ status = WAVEIN_NOTREADY;
+}
+
+
+void
+ audio_wavein::alloc_buffers_mem_( unsigned int buffs, float secs )
+{
+
+
+ unsigned int
+ onebuf_size = 0, tot_size = 0;
+
+
+ //
+ // Release old memory
+ //
+
+ if ( main_buffer )
+ delete[] main_buffer;
+
+
+ if ( wave_headers )
+ delete[] wave_headers;
+
+
+
+ //
+ // Calcs size of the buffers
+ //
+
+ onebuf_size = ( unsigned int )
+ (( float )aud_info.byte_rate() * secs );
+
+
+ tot_size = onebuf_size * buffs;
+
+
+
+
+ //
+ // Allocs memory for the audio buffers
+ //
+
+ main_buffer = new BYTE [ tot_size ];
+
+
+
+ //
+ // Allocs memory for the `WAVEHDR' structures.
+ //
+
+ wave_headers = ( WAVEHDR * )
+ new BYTE [ sizeof( WAVEHDR ) * buffs ];
+
+
+
+ //
+ // Zeros memory.
+ //
+
+ ZeroMemory( main_buffer, tot_size );
+
+ ZeroMemory( wave_headers,
+ sizeof( WAVEHDR ) * buffs );
+
+
+ //
+ // Updates total size of the buffers.
+ //
+
+ mb_size = tot_size;
+
+}
+
+
+void
+ audio_wavein::free_buffers_mem_( void )
+{
+
+
+ //
+ // Frees memory
+ //
+
+ if ( main_buffer )
+ delete[] main_buffer;
+
+
+ if ( wave_headers )
+ delete[] wave_headers;
+
+
+ main_buffer = 0;
+ wave_headers = 0;
+
+}
+
+
+void
+ audio_wavein::init_headers_( void )
+{
+
+
+
+ //
+ // If there is no memory for memory or
+ // headers, simply return.
+ //
+
+ if (( !wave_headers ) || ( !main_buffer ))
+ return;
+
+
+ //
+ // This is the size for one buffer
+ //
+
+ DWORD buf_sz = mb_size / buffers;
+
+
+
+ //
+ // This is the base address for one buffer
+ //
+
+ BYTE * buf_addr = main_buffer;
+
+
+ //
+ // Initializes headers.
+ //
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ wave_headers[ i ].dwBufferLength = mb_size / buffers;
+ wave_headers[ i ].lpData = ( LPSTR ) buf_addr;
+
+ buf_addr += buf_sz;
+ }
+
+}
+
+
+void
+ audio_wavein::prep_headers_( void )
+{
+ MMRESULT err;
+ bool error = false;
+
+
+ //
+ // If there is no memory for memory or
+ // headers, throw error.
+ //
+
+ if (( !wave_headers )
+ || ( !main_buffer ) || ( !wavein_handle ))
+ {} //TODO: throw error!
+
+
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ err = waveInPrepareHeader( wavein_handle,
+ &wave_headers[ i ], sizeof( WAVEHDR ));
+
+
+ if ( err != MMSYSERR_NOERROR )
+ error = true;
+
+ }
+
+
+ if ( error )
+ MessageBox( 0, TEXT("waveInPrepareHeader Error."), 0, 0 );
+
+
+
+}
+
+void
+ audio_wavein::unprep_headers_( void )
+{
+ MMRESULT err;
+ bool error = false;
+
+
+
+ //
+ // If there is no memory for memory or
+ // headers, throw error.
+ //
+
+ if (( !wave_headers )
+ || ( !main_buffer ) || ( !wavein_handle ))
+ {} //TODO: throw error!
+
+
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ err = waveInUnprepareHeader( wavein_handle,
+ &wave_headers[ i ], sizeof( WAVEHDR ));
+
+
+ if ( err != MMSYSERR_NOERROR )
+ error = true;
+
+ }
+
+
+ if ( error )
+ MessageBox( 0, TEXT("waveInUnPrepareHeader Error."), 0, 0 );
+
+}
+
+
+void
+ audio_wavein::add_buffers_to_driver_( void )
+{
+ MMRESULT err;
+ bool error = false;
+
+
+
+ //
+ // If there is no memory for memory or
+ // headers, throw error.
+ //
+
+ if (( !wave_headers )
+ || ( !main_buffer ) || ( !wavein_handle ))
+ {} //TODO: throw error!
+
+
+
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ err = waveInAddBuffer( wavein_handle,
+ &wave_headers[ i ], sizeof( WAVEHDR ));
+
+
+ if ( err != MMSYSERR_NOERROR )
+ error = true;
+
+ }
+
+
+ if ( error )
+ MessageBox( 0, TEXT("waveInAddBuffer Error."), 0, 0 );
+
+}
+
+
+
+void
+ audio_wavein::close( void )
+{
+
+
+
+
+ //
+ // If wavein object is already in the status
+ // NOTREADY, nothing to do.
+ //
+
+ if ( status == WAVEIN_NOTREADY )
+ return;
+
+
+
+ //
+ // If the wavein is recording,
+ // then stop recording and close it.
+ //
+
+ if ( status == WAVEIN_RECORDING )
+ stop_recording();
+
+
+ //
+ // Updating status.
+ //
+
+ status = WAVEIN_NOTREADY;
+
+
+
+
+ //
+ // Wakeing up recording thread, so it
+ // can receive the `MM_WIM_CLOSE' message
+ // then dies.
+ //
+ if ( wakeup_recthread )
+ SetEvent( wakeup_recthread );
+
+
+
+ //
+ // Closing wavein stream
+ //
+
+ while (( waveInClose( wavein_handle ))
+ != MMSYSERR_NOERROR ) Sleep( 1 );
+
+
+
+ //
+ // Release buffers memory.
+ //
+
+ free_buffers_mem_();
+
+
+ //
+ // Re-initialize variables to the
+ // initial state.
+ //
+
+ init_();
+
+}
+
+
+void
+ audio_wavein::open( void )
+{
+
+ MMRESULT err;
+ HANDLE recthread_handle = 0;
+
+
+ //
+ // Checkin the status of the object
+ //
+
+ if ( status != WAVEIN_NOTREADY )
+ {} //TODO: throw error
+
+
+
+ //
+ // Creating the EVENT object that will be signaled
+ // when the recording thread has to wake up.
+ //
+
+ wakeup_recthread =
+ CreateEvent( 0, FALSE, FALSE, 0 );
+
+
+ data_flushed_event =
+ CreateEvent( 0, FALSE, FALSE, 0 );
+
+
+
+ if (( !wakeup_recthread ) || ( !data_flushed_event ))
+ {
+
+
+ status = WAVEIN_ERR;
+
+ MessageBox( 0, TEXT("Thread Error."), 0, 0 );
+
+ //TODO: throw error
+ }
+
+
+
+ //
+ // Inialize buffers for recording audio
+ // data from the wavein audio line.
+ //
+
+ alloc_buffers_mem_( buffers, buf_secs );
+ init_headers_();
+
+
+
+
+
+
+ //
+ // Sound format that will be captured by wavein
+ //
+
+ wave_format.wFormatTag = WAVE_FORMAT_PCM;
+
+ wave_format.nChannels = aud_info.channels();
+ wave_format.nSamplesPerSec = aud_info.sample_rate();
+ wave_format.wBitsPerSample = aud_info.bits();
+ wave_format.nBlockAlign = aud_info.block_align();
+ wave_format.nAvgBytesPerSec = aud_info.byte_rate();
+
+
+
+ //
+ // Creating the recording thread
+ //
+
+ recthread_handle =
+ CreateThread( NULL,
+ 0,
+ audio_wavein::recording_procedure,
+ ( PVOID ) this,
+ 0,
+ &recthread_id
+ );
+
+
+
+ //
+ // Checking thread handle
+ //
+
+ if ( !recthread_handle )
+ {
+
+ //
+ // Updating status
+ //
+
+ status = WAVEIN_ERR;
+
+ MessageBox( 0, TEXT("Thread Error."), 0, 0 );
+ //TODO: throw error
+
+ }
+
+
+ //
+ // We don't need the thread handle anymore,
+ // so we can close it from now. (We'll just
+ // need the thread ID for the `waveInOpen' API)
+ //
+
+ CloseHandle( recthread_handle );
+
+
+
+ //
+ // Opening audio line wavein
+ //
+
+ err = waveInOpen( &wavein_handle,
+ 0,
+ &wave_format,
+ recthread_id,
+ 0,
+ CALLBACK_THREAD
+ );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+
+ //
+ // Updating status
+ //
+
+ status = WAVEIN_ERR;
+
+ if ( err == WAVERR_BADFORMAT )
+ MessageBox( 0, TEXT("waveInOpen Error"), 0, 0 );
+
+
+ //TODO: throw error
+ }
+
+
+ //
+ // Update object status
+ //
+
+ status = WAVEIN_READY;
+
+
+
+ //
+ // Now `audio_wavein' object is ready
+ // for audio recording!
+ //
+}
+
+
+
+void
+ audio_wavein::start_recording( void )
+{
+
+ MMRESULT err;
+ BOOL ev;
+
+
+
+ if (( status != WAVEIN_READY )
+ && ( status != WAVEIN_STOP ))
+ {} //TODO: throw error
+
+
+
+
+ //
+ // Updating to the recording status
+ //
+
+ status = WAVEIN_RECORDING;
+
+
+
+
+ //
+ // Let's prepare header of type WAVEHDR that
+ // we will pass to the driver with our
+ // audio informations, and buffer informations.
+ //
+
+ prep_headers_();
+
+
+
+ //
+ // The waveInAddBuffer function sends an input buffer
+ // to the given waveform-audio input device.
+ // When the buffer is filled, the application is notified.
+ //
+
+ add_buffers_to_driver_();
+
+
+
+
+
+ //
+ // Signaling event for waking up
+ // the recorder thread.
+ //
+
+ ev = SetEvent( wakeup_recthread );
+
+
+ if ( !ev )
+ {
+
+
+ MessageBox( 0, TEXT("Event Error."), 0, 0 );
+
+ }
+
+
+ //
+ // Start recording
+ //
+
+
+ err = waveInStart( wavein_handle );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ //
+ // Updating status
+ //
+
+ status = WAVEIN_ERR;
+
+ MessageBox( 0, TEXT("waveInStart Error."), 0, 0 );
+
+
+ //TODO: throw error
+
+ }
+
+}
+
+
+
+void
+ audio_wavein::stop_recording( void )
+{
+
+
+ MMRESULT err;
+ DWORD wait;
+
+
+ if ( status != WAVEIN_RECORDING )
+ return;
+
+
+
+ status = WAVEIN_FLUSHING;
+
+
+ if ( data_flushed_event )
+ wait = WaitForSingleObject(
+ data_flushed_event, INFINITE
+ );
+
+
+
+ //
+ // waveInReset will make all pending buffer as done.
+ //
+
+ err = waveInReset( wavein_handle );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ //TODO: throw error
+
+ MessageBox( 0, TEXT("waveInReset Error."), 0, 0 );
+
+
+
+ }
+
+
+
+ //
+ // Stop recording.
+ //
+
+ err = waveInStop( wavein_handle );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ //TODO: throw error
+
+ MessageBox( 0, TEXT("waveInStop Error."), 0, 0 );
+
+
+
+ }
+
+
+ //
+ // The waveInUnprepareHeader function cleans up the
+ // preparation performed by the waveInPrepareHeader function.
+ //
+
+ unprep_headers_();
+
+
+
+
+
+
+
+
+
+
+
+ status = WAVEIN_STOP;
+
+}
+
+
+
+DWORD WINAPI
+ audio_wavein::recording_procedure( LPVOID arg )
+{
+
+
+ MSG msg;
+ WAVEHDR * phdr;
+ DWORD wait;
+ audio_wavein * _this = ( audio_wavein * ) arg;
+
+
+
+
+ //
+ // Check the arg pointer
+ //
+
+ if ( _this == 0 )
+ return 0;
+
+
+
+ //
+ // The thread can go to sleep for now.
+ // It will be wake up only when there is audio data
+ // to be recorded.
+ //
+
+ if ( _this->wakeup_recthread )
+ wait = WaitForSingleObject(
+ _this->wakeup_recthread, INFINITE
+ );
+
+
+
+
+
+
+ //
+ // If status of the `audio_wavein' object
+ // is not ready or recording the thread can exit.
+ //
+
+ if (( _this->status != WAVEIN_READY ) &&
+ ( _this->status != WAVEIN_RECORDING ))
+ return 0;
+
+
+
+
+
+
+
+ //
+ // Entering main polling loop
+ //
+
+ while ( GetMessage( &msg, 0, 0, 0 ))
+ {
+
+ switch ( msg.message )
+ {
+
+ case MM_WIM_DATA:
+
+ phdr = ( WAVEHDR * ) msg.lParam;
+
+ if (( _this->status == WAVEIN_RECORDING )
+ || ( _this->status == WAVEIN_FLUSHING ))
+ {
+
+ //
+ // Flushes recorded audio data to
+ // the `audio_receiver' object.
+ //
+
+ _this->audio_rcvd.audio_receive(
+ ( unsigned char * )phdr->lpData,
+ phdr->dwBytesRecorded
+ );
+
+
+ //
+ // Updating `audio_receiver' total
+ // bytes received _AFTER_ calling
+ // `audio_receive' function.
+ //
+
+ _this->audio_rcvd.bytes_received +=
+ phdr->dwBytesRecorded;
+
+
+
+
+ //
+ // If status is not flushing data, then
+ // we can re-add the buffer for reusing it.
+ // Otherwise, if we are flushing pending data,
+ // we cannot re-add buffer because we don't need
+ // it anymore
+ //
+
+ if ( _this->status != WAVEIN_FLUSHING )
+ {
+
+ //
+ // Let the audio driver reuse the buffer
+ //
+
+ waveInAddBuffer( _this->wavein_handle,
+ phdr, sizeof( WAVEHDR ));
+
+
+ } else {
+
+ //
+ // If we are flushing pending data, we have
+ // to prepare to stop recording.
+ // Set WAVEHDR flag to 0, and fires the event
+ // `data_flushed_event', that will wake up
+ // the main thread that is sleeping into
+ // wavein_in::stop_recording() member function,
+ // waiting the last `MM_WIM_DATA' message that
+ // contain pending data.
+ //
+
+
+
+
+ phdr->dwFlags = 0;
+
+ SetEvent( _this->data_flushed_event );
+
+
+ //
+ // The recording is gooing to stop, so the
+ // recording thread can go to sleep!
+ //
+
+ wait = WaitForSingleObject(
+ _this->wakeup_recthread, INFINITE );
+
+ }
+
+
+ }//if WAVEIN_RECORDING || WAVEIN_FLUSHING
+
+ break;
+
+
+
+
+
+
+
+
+
+ case MM_WIM_CLOSE:
+
+ //
+ // The thread can exit now.
+ //
+
+ return 0;
+
+ break;
+
+
+
+ } //end switch( msg.message )
+
+ } //end while( GetMessage( ... ))
+
+ return 0;
+}
+
+
+
+
+
+
+_AUDIO_NAMESPACE_END_
--- /dev/null
+#ifndef _AUDIOWAVEIN_H_
+#define _AUDIOWAVEIN_H_
+
+
+
+#include "audio_def.hpp"
+#include "audio_format.hpp"
+#include "audio_receiver.hpp"
+
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+
+enum audio_wavein_status { WAVEIN_NOTREADY, WAVEIN_READY,
+ WAVEIN_RECORDING, WAVEIN_ERR,
+ WAVEIN_STOP, WAVEIN_FLUSHING
+
+ };
+
+
+
+
+
+class audio_wavein
+{
+ private:
+
+
+
+ //
+ // The new recording thread sends message to this procedure
+ // about open recording, close, and sound data recorded
+ //
+
+ static DWORD WINAPI recording_procedure( LPVOID );
+
+ //
+ // When this event is signaled, then the previsiously created
+ // recording thread will wake up and start recording audio
+ // and will pass audio data to an `audio_receiver' object.
+ //
+
+ HANDLE wakeup_recthread;
+ HANDLE data_flushed_event;
+
+
+
+
+ protected:
+
+
+//TODO: puts these structs in private?!
+
+
+
+
+ //
+ // Audio wavein device stuff
+ //
+
+ WAVEFORMATEX wave_format;
+ WAVEHDR * wave_headers;
+ HWAVEIN wavein_handle;
+
+
+
+
+
+ audio_format aud_info;
+
+ audio_receiver & audio_rcvd;
+
+
+
+ //
+ // Audio Recorder Thread id
+ //
+
+ DWORD recthread_id;
+
+
+
+
+ //
+ // Object status
+ //
+
+ audio_wavein_status status;
+
+
+
+
+
+
+
+ //
+ // How many seconds of audio
+ // can record the internal buffer
+ // before flushing audio data
+ // to the `audio_receiver' class?
+ //
+
+ float buf_secs;
+
+
+ //
+ // The temporary buffers for the audio
+ // data incoming from the wavein device
+ // and its size, and its total number.
+ //
+
+ BYTE * main_buffer;
+ unsigned int mb_size;
+
+ unsigned int buffers;
+
+
+
+
+
+ //
+ // Protected Functions
+ //
+
+
+ //initialize all structures and variables.
+ void init_( void );
+
+ void alloc_buffers_mem_( unsigned int, float );
+ void free_buffers_mem_( void );
+
+ void init_headers_( void );
+ void prep_headers_( void );
+ void unprep_headers_( void );
+ void add_buffers_to_driver_( void );
+
+
+
+
+
+
+
+ public:
+
+
+ //
+ // Ctors
+ //
+
+ audio_wavein(
+ const audio_format & a_info, audio_receiver & a_receiver )
+
+ : wave_headers( 0 ),
+ aud_info( a_info ), audio_rcvd( a_receiver ),
+ status( WAVEIN_NOTREADY ), main_buffer( 0 ), mb_size( 0 ),
+ buffers( _AUDIO_DEFAULT_WAVEINBUFFERS )
+ {
+
+ //
+ // Initializing internal wavein data
+ //
+
+
+ init_();
+
+ aud_info = a_info;
+ }
+
+
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ ~audio_wavein( void )
+ {
+
+ //close(); TODO!
+
+ }
+
+
+
+ //
+ // Public functions
+ //
+
+ void open( void );
+ void close ( void );
+
+
+ void start_recording( void );
+ void stop_recording( void );
+
+
+
+ audio_wavein_status current_status ( void ) const
+ {
+ return status;
+ }
+
+ float buffer_secs( void ) const
+ { return buf_secs; }
+
+
+ void buffer_secs( float bsecs )
+ {
+ //
+ // Some checking
+ //
+
+ if ( bsecs <= 0 )
+ return;
+
+
+ //
+ // Set seconds lenght for each
+ // buffer.
+ //
+
+ buf_secs = bsecs;
+ }
+
+
+ unsigned int total_buffers( void ) const
+ { return buffers; }
+
+
+
+ void total_buffers( unsigned int tot_bufs )
+ {
+
+ //
+ // Some checking
+ //
+
+ if ( tot_bufs == 0 )
+ return;
+
+
+ //
+ // Sets the number of total buffers.
+ //
+
+ buffers = tot_bufs;
+ }
+
+
+ audio_format format( void ) const
+ { return aud_info; }
+
+
+
+};
+
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+#endif //ifdef _AUDIOWAVEIN_H_
--- /dev/null
+/*
+ * PROJECT: ReactOS Sound Record Application
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/applications/sndrec32/audio_waveout.cpp
+ * PURPOSE: Audio WaveOut
+ * PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+ */
+
+
+#include "stdafx.h"
+#include "audio_waveout.hpp"
+
+
+_AUDIO_NAMESPACE_START_
+
+
+
+void
+audio_waveout::init_( void )
+{
+
+ ZeroMemory(( LPVOID ) &wave_format,
+ sizeof( WAVEFORMATEX ));
+
+ wave_format.cbSize = sizeof( WAVEFORMATEX );
+
+ waveout_handle = 0;
+
+ playthread_id = 0;
+ wakeup_playthread = 0;
+
+ buf_secs = _AUDIO_DEFAULT_WAVEOUTBUFSECS;
+
+
+ status = WAVEOUT_NOTREADY;
+
+}
+
+
+
+
+void
+audio_waveout::alloc_buffers_mem_( unsigned int buffs, float secs )
+{
+
+
+ unsigned int
+ onebuf_size = 0, tot_size = 0;
+
+
+ //
+ // Release old memory
+ //
+
+ if ( main_buffer )
+ delete[] main_buffer;
+
+
+ if ( wave_headers )
+ delete[] wave_headers;
+
+
+
+ //
+ // Calcs size of the buffers
+ //
+
+ onebuf_size = ( unsigned int )
+ (( float )aud_info.byte_rate() * secs );
+
+
+ tot_size = onebuf_size * buffs;
+
+
+
+
+ //
+ // Allocs memory for the audio buffers
+ //
+
+ main_buffer = new BYTE [ tot_size ];
+
+
+
+ //
+ // Allocs memory for the `WAVEHDR' structures.
+ //
+
+ wave_headers = ( WAVEHDR * )
+ new BYTE [ sizeof( WAVEHDR ) * buffs ];
+
+
+
+ //
+ // Zeros memory.
+ //
+
+ ZeroMemory( main_buffer, tot_size );
+
+ ZeroMemory( wave_headers,
+ sizeof( WAVEHDR ) * buffs );
+
+
+ //
+ // Updates total size of the buffers.
+ //
+
+ mb_size = tot_size;
+}
+
+
+void
+audio_waveout::init_headers_( void )
+{
+
+
+
+ //
+ // If there is no memory for memory or
+ // headers, simply return.
+ //
+
+ if (( !wave_headers ) || ( !main_buffer ))
+ return;
+
+
+ //
+ // This is the size for one buffer
+ //
+
+ DWORD buf_sz = mb_size / buffers;
+
+
+
+ //
+ // This is the base address for one buffer
+ //
+
+ BYTE * buf_addr = main_buffer;
+
+
+
+ ZeroMemory( wave_headers, sizeof( WAVEHDR ) * buffers );
+
+
+ //
+ // Initializes headers.
+ //
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+
+ //
+ // Sets the correct base address and
+ // lenght for the little buffer.
+ //
+
+ wave_headers[ i ].dwBufferLength = mb_size / buffers;
+ wave_headers[ i ].lpData = ( LPSTR ) buf_addr;
+
+ //
+ // Unsets the WHDR_DONE flag.
+ //
+
+ wave_headers[ i ].dwFlags &= ~WHDR_DONE;
+
+
+
+ //
+ // Sets the WAVEHDR user data with an
+ // unique little buffer ID#
+ //
+
+ wave_headers[ i ].dwUser = ( unsigned int ) i;
+
+
+
+ //
+ // Increments little buffer base address.
+ //
+
+ buf_addr += buf_sz;
+ }
+
+}
+
+
+void
+audio_waveout::prep_headers_( void )
+{
+ MMRESULT err;
+ bool error = false;
+
+
+ //
+ // If there is no memory for memory or
+ // headers, throw error.
+ //
+
+ if (( !wave_headers )
+ || ( !main_buffer ) || ( !waveout_handle ))
+ {} //TODO: throw error!
+
+
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ err = waveOutPrepareHeader( waveout_handle,
+ &wave_headers[ i ], sizeof( WAVEHDR ));
+
+
+ if ( err != MMSYSERR_NOERROR )
+ error = true;
+
+ }
+
+
+ if ( error )
+ {} //TODO: throw error indicating which
+ //header i-th is errorneous
+
+
+
+}
+
+void
+audio_waveout::unprep_headers_( void )
+{
+ MMRESULT err;
+ bool error = false;
+
+
+
+ //
+ // If there is no memory for memory or
+ // headers, throw error.
+ //
+
+ if (( !wave_headers )
+ || ( !main_buffer ) || ( !waveout_handle ))
+ {} //TODO: throw error!
+
+
+
+ for ( unsigned int i = 0; i < buffers; ++i )
+ {
+ err = waveOutUnprepareHeader( waveout_handle,
+ &wave_headers[ i ], sizeof( WAVEHDR ));
+
+
+ if ( err != MMSYSERR_NOERROR )
+ error = true;
+
+ }
+
+
+ if ( error )
+ {} //TODO: throw error indicating which
+ //header i-th is errorneous
+
+}
+
+
+
+
+
+
+
+
+
+void
+audio_waveout::free_buffers_mem_( void )
+{
+
+
+
+ //
+ // Frees memory
+ //
+
+ if ( main_buffer )
+ delete[] main_buffer;
+
+
+ if ( wave_headers )
+ delete[] wave_headers;
+
+
+ main_buffer = 0;
+ wave_headers = 0;
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void
+audio_waveout::open( void )
+{
+
+ MMRESULT err;
+ HANDLE playthread_handle = 0;
+
+
+ //
+ // Checkin the status of the object
+ //
+
+ if ( status != WAVEOUT_NOTREADY )
+ {} //TODO: throw error
+
+
+ //
+ // Creating the EVENT object that will be signaled
+ // when the playing thread has to wake up.
+ //
+
+ wakeup_playthread =
+ CreateEvent( 0, FALSE, FALSE, 0 );
+
+ if ( !wakeup_playthread )
+ {
+
+
+ status = WAVEOUT_ERR;
+
+ //TODO: throw error
+ }
+
+
+
+ //
+ // Inialize buffers for recording audio
+ // data from the wavein audio line.
+ //
+
+ alloc_buffers_mem_( buffers, buf_secs );
+ init_headers_();
+
+
+
+
+
+
+ //
+ // Sound format that will be captured by wavein
+ //
+
+ wave_format.wFormatTag = WAVE_FORMAT_PCM;
+
+ wave_format.nChannels = aud_info.channels();
+ wave_format.nSamplesPerSec = aud_info.sample_rate();
+ wave_format.wBitsPerSample = aud_info.bits();
+ wave_format.nBlockAlign = aud_info.block_align();
+ wave_format.nAvgBytesPerSec = aud_info.byte_rate();
+
+
+
+ //
+ // Creating the recording thread
+ //
+
+ playthread_handle =
+ CreateThread( NULL,
+ 0,
+ audio_waveout::playing_procedure,
+ ( PVOID ) this,
+ 0,
+ &playthread_id
+ );
+
+
+
+ //
+ // Checking thread handle
+ //
+
+ if ( !playthread_handle )
+ {
+
+ //
+ // Updating status
+ //
+
+ status = WAVEOUT_ERR;
+ //TODO: throw error
+
+ }
+
+
+ //
+ // We don't need the thread handle anymore,
+ // so we can close it from now. (We'll just
+ // need the thread ID for the `waveInOpen' API)
+ //
+
+ CloseHandle( playthread_handle );
+
+
+
+ //
+ // Reset the `audio_source' to the start
+ // position.
+ //
+
+ audio_buf.set_position_start();
+
+
+
+
+ //
+ // Opens the WAVE_OUT device.
+ //
+
+ err = waveOutOpen(
+ &waveout_handle,
+ WAVE_MAPPER,
+ &wave_format,
+ playthread_id,
+ 0,
+ CALLBACK_THREAD | WAVE_ALLOWSYNC
+ );
+
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ MessageBox(0, _T("waveOutOpen Error"), 0, 0);
+ //TODO: throw error
+
+ }
+
+
+
+
+ status = WAVEOUT_READY;
+
+
+}
+
+
+
+void
+audio_waveout::play( void )
+{
+
+
+ MMRESULT err;
+ unsigned int i;
+ BOOL ev;
+
+
+ if ( !main_buffer )
+ { return; } //TODO; throw error, or assert
+
+
+
+
+ //
+ // If the status is PAUSED, we have to
+ // resume the audio playing.
+ //
+ if ( status == WAVEOUT_PAUSED )
+ {
+
+ //
+ // Updates status.
+ //
+
+ status = WAVEOUT_PLAYING;
+
+
+ //
+ // Tells to the driver to resume
+ // audio playing.
+ //
+
+ waveOutRestart( waveout_handle );
+
+
+ //
+ // Wakeup playing thread.
+ //
+
+ ev = SetEvent( wakeup_playthread );
+
+ return;
+
+ } //if status == WAVEOUT_PAUSED
+
+
+
+
+
+ if ( status != WAVEOUT_READY )
+ return;
+
+
+
+
+ //
+ // Prepares WAVEHDR structures.
+ //
+
+ prep_headers_();
+
+
+
+ //
+ // Sets correct status.
+ //
+
+ status = WAVEOUT_PLAYING;
+
+
+
+ //
+ // Reads the audio from the start.
+ //
+
+ audio_buf.set_position_start();
+
+
+
+
+ //
+ // Reads the first N bytes from the audio
+ // buffer, where N = the total size of all
+ // little buffers.
+ //
+
+ audio_buf.read( main_buffer, mb_size );
+
+
+
+
+
+
+ //
+ // Wakeup the playing thread.
+ //
+
+ ev = SetEvent( wakeup_playthread );
+
+
+
+
+ //
+ // Sends all the little buffers to the
+ // audio driver, so it can play the sound
+ // data.
+ //
+
+ for ( i = 0; i < buffers; ++ i )
+ {
+
+
+ err = waveOutWrite( waveout_handle, &wave_headers[ i ], sizeof( WAVEHDR ));
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+
+ MessageBox(0, _T("waveOutWrite Error"), 0, 0);
+
+ //TODO: throw error
+ }
+
+ }
+
+}
+
+
+void
+audio_waveout::pause( void )
+{
+
+ MMRESULT err;
+
+
+ //
+ // If the waveout object is not playing audio,
+ // do nothing.
+ //
+
+ if ( status == WAVEOUT_PLAYING )
+ {
+
+ //
+ // Updating status.
+ //
+
+ status = WAVEOUT_PAUSED;
+
+
+ //
+ // Tells to audio driver to pause audio.
+ //
+
+ err = waveOutPause( waveout_handle );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ MessageBox(0, _T("waveOutPause Error"), 0, 0);
+ //TODO: throw error
+
+ }
+
+ }
+
+}
+
+
+void
+audio_waveout::stop( void )
+{
+
+ MMRESULT err;
+
+
+ status = WAVEOUT_STOP;
+
+
+ err = waveOutReset( waveout_handle );
+
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ MessageBox(0, _T("err waveout reset.\n"),_T("ERROR"), 0);
+ //TODO: throw error
+
+ }
+
+
+
+ //
+ // Sets the start position of the audio
+ // buffer.
+ //
+
+ audio_buf.set_position_start();
+
+
+ unprep_headers_();
+
+
+ init_headers_();
+
+
+ status = WAVEOUT_READY;
+
+}
+
+void
+audio_waveout::close( void )
+{
+
+ MMRESULT err;
+
+
+ //
+ // If the `wave_out' object is playing audio,
+ // or it is in paused state, we have to call
+ // the `stop' member function, to flush
+ // pending buffers.
+ //
+
+ if (( status == WAVEOUT_PLAYING )
+ || ( status== WAVEOUT_PAUSED ))
+ {
+
+ stop();
+
+ }
+
+
+
+ //
+ // When we have flushed all pending buffers,
+ // the wave out handle can be successfully closed.
+ //
+
+ err = waveOutClose( waveout_handle );
+
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+
+ MessageBox(0, _T("waveOutClose Error"), 0, 0);
+ //TODO: throw error
+
+ }
+
+ free_buffers_mem_();
+
+}
+
+
+DWORD WINAPI
+audio_waveout::playing_procedure( LPVOID arg )
+{
+ MSG msg;
+ WAVEHDR * phdr;
+ DWORD wait;
+ MMRESULT err;
+ audio_waveout * _this = ( audio_waveout * ) arg;
+ unsigned int read_size;
+
+
+
+ //
+ // Check the arg pointer
+ //
+
+ if ( _this == 0 )
+ return 0;
+
+
+
+ //
+ // The thread can go to sleep for now.
+ // It will be wake up only when there is audio data
+ // to be recorded.
+ //
+
+ if ( _this->wakeup_playthread )
+ wait = WaitForSingleObject(
+ _this->wakeup_playthread, INFINITE
+ );
+
+
+
+ //
+ // Entering main polling loop
+ //
+
+ while ( GetMessage( &msg, 0, 0, 0 ))
+ {
+
+ switch ( msg.message )
+ {
+
+ case MM_WOM_DONE:
+
+ phdr = ( WAVEHDR * ) msg.lParam;
+
+
+ //
+ // If the status of the `wave_out' object
+ // is different than playing, then the thread
+ // can go to sleep.
+ //
+
+ if (( _this->status != WAVEOUT_PLAYING )
+ && ( _this->wakeup_playthread ))
+ {
+
+ wait = WaitForSingleObject(
+ _this->wakeup_playthread,
+ INFINITE
+ );
+ }
+
+ //TODO: quando il thread si risveglia, deve
+ //entrare nel prossimo if o no? o metter un else { ?
+
+
+
+ if ( phdr->dwFlags & WHDR_DONE )
+ {
+
+ read_size =
+ _this->audio_buf.read(
+ ( BYTE * ) phdr->lpData,
+ phdr->dwBufferLength
+ );
+
+
+ if ( read_size )
+ {
+ phdr->dwBufferLength = read_size;
+
+ phdr->dwFlags &= ~WHDR_DONE;
+
+ err = waveOutWrite(
+ _this->waveout_handle,
+ phdr,
+ sizeof( WAVEHDR )
+ );
+
+ if ( err != MMSYSERR_NOERROR )
+ {
+ MessageBox(0, _T("waveOutWrite Error"), 0, 0);
+ //TODO: throw error
+ }
+
+
+ } else {
+
+ //
+ // Here `read_sizep' is 0
+ //
+
+ if ( phdr->dwUser == ( _this->buffers - 1 ))
+ {
+
+ //
+ // Here `read_size' and the buffer user
+ // data, that contain a buffer ID#,
+ // is equal to the number of the total
+ // buffers - 1. This means that this is the
+ // _LAST_ little buffer that has been played
+ // by the audio driver. We can STOP the
+ // `wave_out' object now, or restart the
+ // sound playing, if we have a infinite loop.
+ //
+
+
+ _this->stop();
+
+ //
+ // Let the thread go to sleep.
+ //
+
+ if ( _this->audio_buf.play_finished )
+ _this->audio_buf.play_finished();
+
+
+ if ( _this->wakeup_playthread )
+ wait = WaitForSingleObject(
+ _this->wakeup_playthread,
+ INFINITE
+ );
+
+ }
+
+ } //if read_size != 0
+
+ } //( phdr->dwFlags & WHDR_DONE )
+
+
+ break; // end case
+
+
+
+ case MM_WOM_CLOSE:
+ //
+ // The thread can exit now.
+ //
+
+ return 0;
+
+ break;
+
+
+ case MM_WOM_OPEN:
+
+ //
+ // Do nothing.
+ //
+
+ break;
+
+
+ } //end switch( msg.message )
+
+ } //end while( GetMessage( ... ))
+
+ return 0;
+}
+
+_AUDIO_NAMESPACE_END_
--- /dev/null
+#ifndef _AUDIOWAVEOUT__H_
+#define _AUDIOWAVEOUT__H_
+
+
+#include "audio_def.hpp"
+#include "audio_format.hpp"
+#include "audio_producer.hpp"
+
+
+
+_AUDIO_NAMESPACE_START_
+
+enum audio_waveout_status { WAVEOUT_NOTREADY, WAVEOUT_READY,
+ WAVEOUT_PLAYING, WAVEOUT_ERR,
+ WAVEOUT_PAUSED, WAVEOUT_STOP
+
+ };
+
+
+class audio_waveout
+{
+
+ friend class audio_buffer;
+
+
+
+ private:
+
+
+ static DWORD WINAPI playing_procedure( LPVOID );
+
+
+
+ HANDLE wakeup_playthread;
+
+
+
+
+ protected:
+
+
+ WAVEFORMATEX wave_format;
+ WAVEHDR * wave_headers;
+ HWAVEOUT waveout_handle;
+
+
+
+
+
+ const audio_format & aud_info;
+ audio_producer & audio_buf;
+
+
+
+
+
+
+ //
+ // Audio Playing Thread id
+ //
+
+ DWORD playthread_id;
+
+
+
+
+
+ audio_waveout_status status;
+
+
+
+
+ float buf_secs;
+
+
+
+ //
+ // The temporary buffers for the audio
+ // data outgoing to the waveout device
+ // and its size, and its total number.
+ //
+
+
+ //base address for entire memory
+ BYTE * main_buffer;
+
+ //size in bytes for the entire memory
+ unsigned int mb_size;
+
+ //number of little buffers
+ unsigned int buffers;
+
+
+
+
+
+
+ //
+ // Protected Functions
+ //
+
+ void init_( void );
+ void alloc_buffers_mem_( unsigned int, float );
+ void free_buffers_mem_( void );
+
+
+ void init_headers_( void );
+ void prep_headers_( void );
+ void unprep_headers_( void );
+
+
+
+
+
+
+
+ public:
+
+ //
+ // Ctors
+ //
+
+ audio_waveout( const audio_format & aud_fmt,
+ audio_producer & a_buf )
+
+ : wave_headers( 0 ), aud_info( aud_fmt ),
+ audio_buf( a_buf ), status( WAVEOUT_NOTREADY ),
+ main_buffer( 0 ), mb_size( 0 ),
+ buffers( _AUDIO_DEFAULT_WAVEOUTBUFFERS )
+ {
+
+ //
+ // Initializing internal wavein data
+ //
+
+
+ init_();
+
+ }
+
+
+
+
+
+
+ //
+ // Dtor
+ //
+
+ ~audio_waveout( void )
+ { }
+
+
+
+
+ //
+ // Public Functions
+ //
+
+ void open ( void );
+ void play ( void );
+ void pause ( void );
+ void stop ( void );
+ void close ( void );
+
+
+ audio_waveout_status current_status( void )
+ { return status; }
+
+
+
+
+
+
+
+
+};
+
+
+
+_AUDIO_NAMESPACE_END_
+
+
+
+
+#endif //ifdef _AUDIOWAVEOUT__H_
--- /dev/null
+#ifndef _AUDIO__H_
+#define _AUDIO__H_
+
+
+#include "audio_def.hpp"
+#include "audio_wavein.hpp"
+#include "audio_waveout.hpp"
+#include "audio_resampler_acm.hpp"
+#include "audio_format.hpp"
+#include "audio_membuffer.hpp"
+#include "audio_producer.hpp"
+#include "audio_receiver.hpp"
+
+
+
+
+#endif //ifdef _KKAUDIO__H_
+
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by reactOS_sndrec32.rc
+//
+#define IDC_MYICON 2
+#define IDD_REACTOS_SNDREC32_DIALOG 102
+#define IDS_APP_TITLE 103
+#define IDD_ABOUTBOX 103
+#define IDM_ABOUT 104
+#define IDI_REACTOS_SNDREC32 107
+#define IDI_REACTOS_SNDREC32LL 107
+#define IDI_SMALL 108
+#define IDC_REACTOS_SNDREC32 109
+#define IDR_MAINFRAME 128
+#define IDB_BITMAP1 132
+#define IDB_BITMAP_REC 132
+#define IDB_BITMAP2_START 133
+#define IDB_BITMAP2_END 134
+#define IDB_BITMAP2_PLAY 135
+#define IDB_BITMAP2_STOP 136
+#define IDB_BITMAP2_REC 137
+#define IDI_ICON1 138
+#define IDR_MENU1 139
+#define ID_FILE_NEW 32771
+#define ID_FILE_OPEN 32772
+#define ID_FILE_SAVE 32773
+#define ID_FILE_SAVEAS 32774
+#define ID_FILE_EXIT 32775
+#define ID__ABOUT 32776
+#define ID_EXIT 32777
+#define ID_NEW 32778
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 140
+#define _APS_NEXT_COMMAND_VALUE 32779
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
--- /dev/null
+/*
+* PROJECT: ReactOS Sound Record Application
+* LICENSE: GPL - See COPYING in the top level directory
+* FILE: base/applications/sndrec32/sndrec32.cpp
+* PURPOSE: Application Startup
+* PROGRAMMERS: Marco Pagliaricci <ms_blue (at) hotmail (dot) it>
+*/
+
+
+
+#include "stdafx.h"
+#include "sndrec32.h"
+
+#include "kkaudio.hpp"
+
+
+
+HINSTANCE hInst;
+TCHAR szTitle[MAX_LOADSTRING];
+TCHAR szWindowClass[MAX_LOADSTRING];
+
+
+ATOM MyRegisterClass(HINSTANCE hInstance);
+BOOL InitInstance(HINSTANCE, int);
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+
+
+
+HWND main_win;
+HWND slider;
+HWND buttons[5];
+HBITMAP butbmps[5];
+WNDPROC buttons_std_proc;
+
+BOOL butdisabled[5];
+BOOL stopped_flag;
+BOOL isnew;
+
+
+DWORD slider_pos;
+WORD slider_min;
+WORD slider_max;
+
+long long samples_max;
+
+OPENFILENAME ofn;
+TCHAR file_path[MAX_PATH];
+BOOL path_set;
+
+using snd::audio_membuffer;
+using snd::audio_wavein;
+using snd::audio_waveout;
+
+audio_membuffer * AUD_BUF;
+audio_waveout * AUD_OUT;
+audio_wavein * AUD_IN;
+
+
+BOOL s_recording;
+
+
+int APIENTRY _tWinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPTSTR lpCmdLine,
+ int nCmdShow)
+{
+
+ UNREFERENCED_PARAMETER(hPrevInstance);
+ UNREFERENCED_PARAMETER(lpCmdLine);
+
+
+ MSG msg;
+ HACCEL hAccelTable;
+
+ InitCommonControls();
+
+
+
+
+
+
+
+
+ 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 ));
+
+
+
+
+
+
+ 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;
+
+
+
+ slider_pos = 0;
+ slider_min = 0;
+ slider_max = 32767;
+
+
+ stopped_flag = FALSE;
+ path_set = FALSE;
+ isnew = TRUE;
+
+
+
+ samples_max = AUD_buffer.total_samples();
+
+
+
+
+ LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
+ LoadString(hInstance, IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING);
+ MyRegisterClass(hInstance);
+
+
+ if (!InitInstance (hInstance, nCmdShow))
+ {
+ MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0);
+ return FALSE;
+ }
+
+ hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_REACTOS_SNDREC32));
+
+
+
+
+
+
+ s_recording = false;
+
+
+
+
+ AUD_wavein.open();
+ AUD_waveout.open();
+
+
+
+
+
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ AUD_waveout.close();
+ 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_REACTOS_SNDREC32LL));
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(16);
+ wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
+ wcex.lpszClassName = szWindowClass;
+ wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_REACTOS_SNDREC32LL));
+
+
+ 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;
+}
+
+
+//
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ int wmId, wmEvent;
+ RECT rect;
+ PAINTSTRUCT ps;
+ HDC hdc;
+
+
+ //
+ // 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 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;
+
+ }
+
+ butdisabled[ i ] = TRUE;
+
+
+
+ //
+ // Realize the button bmp image
+ //
+
+ SendMessage(buttons[i], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[i]);
+
+
+ UpdateWindow( buttons[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
+ //
+
+ //slider_min = 0;
+ //slider_max = 100;
+
+ SendMessage(
+ slider,
+ TBM_SETRANGE,
+ (WPARAM)TRUE,
+ (LPARAM)MAKELONG(slider_min,slider_max)
+ );
+
+
+ UpdateWindow( slider );
+
+
+ //
+ // Enables REC button.
+ //
+
+ butdisabled[ BUTREC_ID ] = FALSE;
+
+
+
+
+ break;
+
+
+
+ //
+ // Implements slider logic
+ //
+
+ case WM_HSCROLL :
+ {
+ switch( LOWORD( wParam ))
+ {
+
+ case SB_ENDSCROLL:
+ break;
+
+ case SB_PAGERIGHT:
+ case SB_PAGELEFT:
+ case TB_THUMBTRACK:
+ slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0);
+ 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();
+
+ butdisabled[ BUTREC_ID ] = FALSE;
+ butdisabled[ BUTSTART_ID ] = TRUE;
+ butdisabled[ BUTEND_ID ] = TRUE;
+ butdisabled[ BUTSTOP_ID ] = TRUE;
+ butdisabled[ BUTPLAY_ID ] = TRUE;
+
+ samples_max = AUD_BUF->total_samples();
+ slider_pos = 0;
+
+ SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
+
+ }
+
+
+
+ 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 );
+ }
+
+ break;
+
+
+
+
+ case ID__ABOUT:
+
+
+
+ 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 );
+
+ }
+
+ break;
+
+ case ID_EXIT:
+ DestroyWindow( hWnd );
+ break;
+
+
+ //
+ // Sndrec32 buttons routines
+ //
+
+ case BUTSTART_ID:
+ Beep(200,200);
+ break;
+
+
+ case BUTEND_ID:
+ Beep(300,200);
+ break;
+
+ case BUTPLAY_ID:
+
+ AUD_OUT->play();
+
+ butdisabled[ BUTSTART_ID ] = TRUE;
+ butdisabled[ BUTEND_ID ] = TRUE;
+ butdisabled[ BUTREC_ID ] = TRUE;
+ butdisabled[ BUTPLAY_ID ] = TRUE;
+
+ SetTimer( hWnd, 1, 250, 0 );
+
+ break;
+
+ case BUTSTOP_ID:
+ if ( s_recording )
+ {
+ s_recording = FALSE;
+
+ AUD_IN->stop_recording();
+
+ butdisabled[ BUTSTART_ID ] = FALSE;
+ butdisabled[ BUTEND_ID ] = FALSE;
+ butdisabled[ BUTREC_ID ] = FALSE;
+ butdisabled[ BUTPLAY_ID ] = FALSE;
+
+
+
+ //
+ // 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 );
+
+ } else {
+
+ AUD_OUT->pause();
+
+ butdisabled[ BUTSTART_ID ] = FALSE;
+ butdisabled[ BUTEND_ID ] = FALSE;
+ butdisabled[ BUTREC_ID ] = FALSE;
+ butdisabled[ BUTPLAY_ID ] = FALSE;
+
+ }
+
+ KillTimer( hWnd, 1 );
+
+ break;
+
+ case BUTREC_ID:
+
+ s_recording = TRUE;
+
+ samples_max = AUD_BUF->total_samples();
+
+ AUD_IN->start_recording();
+
+ butdisabled[ BUTSTOP_ID ] = FALSE;
+ butdisabled[ BUTSTART_ID ] = TRUE;
+ butdisabled[ BUTEND_ID ] = TRUE;
+ butdisabled[ BUTREC_ID ] = TRUE;
+ butdisabled[ BUTPLAY_ID ] = TRUE;
+
+ isnew = FALSE;
+
+
+
+ SetTimer( hWnd, 1, 150, 0 );
+
+ break;
+
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ break;
+
+
+ case WM_TIMER:
+
+ if ( stopped_flag )
+ {
+ KillTimer(hWnd, 1);
+ slider_pos = 0;
+
+ butdisabled[ BUTPLAY_ID ] = FALSE;
+
+ stopped_flag = FALSE;
+ }
+
+ SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
+
+
+
+ break;
+
+
+
+ case WM_PAINT:
+
+ InvalidateRect( hWnd, &rect, TRUE );
+ hdc = BeginPaint(hWnd, &ps);
+
+ EndPaint(hWnd, &ps);
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+}
+
+
+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 )
+ {
+ DWORD t = GetLastError();
+ TCHAR p[100];
+ wsprintf(p,TEXT("Errore n: %i"),t);
+
+ MessageBox(
+ main_win,
+ //TEXT("Cannot read RIFF header."),
+ p,
+ 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;
+
+
+ /*
+ unsigned char * gg = (unsigned char*)&bytes_recorded_in_wav;
+
+ gg[0] = gg[3];
+ gg[1] = gg[2];
+
+ bytes_recorded_in_wav = (DWORD) *gg;
+
+
+
+ TCHAR p [100];
+ wsprintf(p,TEXT("bytes: %i"),bytes_recorded_in_wav);
+ MessageBox(0,p,0,0);
+
+ */
+
+ 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 );
+
+ butdisabled[ BUTPLAY_ID ] = FALSE;
+ butdisabled[ BUTSTOP_ID ] = FALSE;
+ butdisabled[ BUTEND_ID ] = FALSE;
+ butdisabled[ BUTSTART_ID ] = FALSE;
+ butdisabled[ BUTREC_ID ] = FALSE;
+
+
+
+ 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;
+}
+
+
+
+void l_play_finished ( void )
+{
+
+ stopped_flag = 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 )
+{
+
+
+
+
+
+}
+VOID disable_but( DWORD id )
+{
+
+
+
+}
+
+
--- /dev/null
+#pragma once
+
+#include "resource.h"
+
+
+
+#define MAX_LOADSTRING 100
+
+#define MAINWINDOW_W 350
+#define MAINWINDOW_H 190
+
+
+#define CONTROLS_CX 10
+
+#define INITIAL_BUFREC_SECONDS 30.0f
+
+
+#define BUTSTART_ID 0
+#define BUTEND_ID 1
+#define BUTPLAY_ID 2
+#define BUTSTOP_ID 3
+#define BUTREC_ID 4
+#define SLIDER_ID 5
+
+#define BUTTONS_H 30
+#define BUTTONS_W 60
+#define BUTTONS_CY 100
+#define BUTTONS_CX CONTROLS_CX
+#define BUTTONS_SPACE 5
+
+
+#define SLIDER_CX CONTROLS_CX
+#define SLIDER_CY 65
+#define SLIDER_H 30
+#define SLIDER_W 320
+
+
+
+
+struct riff_hdr
+{
+ DWORD magic;
+ DWORD chunksize;
+ DWORD format;
+};
+
+
+struct wave_hdr
+{
+
+ DWORD Subchunkid;
+ DWORD Subchunk1Size;
+ WORD AudioFormat;
+ WORD NumChannels;
+ DWORD SampleRate;
+ DWORD ByteRate;
+ WORD BlockAlign;
+ WORD BitsPerSample;
+};
+
+struct data_chunk
+{
+ DWORD subc;
+ DWORD subc_size;
+ //unsigned char data[];
+};
+
+
+
+//
+// Functions prototypes
+//
+LRESULT CALLBACK
+Buttons_proc(HWND, UINT, WPARAM, LPARAM);
+
+
+BOOL
+write_wav( TCHAR * );
+
+BOOL
+open_wav( TCHAR * );
+
+
+VOID enable_but( DWORD );
+VOID disable_but( DWORD );
+
+
+
+void
+l_play_finished ( void );
+
+void
+l_audio_arrival ( unsigned int );
+
+void
+l_buffer_resized ( unsigned int );
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="sndrec32" type="win32gui" installbase="system32" installname="sndrec32.exe">
+ <include base="sndrec32">.</include>
+ <library>winmm</library>
+ <library>user32</library>
+ <library>kernel32</library>
+ <library>msacm32</library>
+ <library>comctl32</library>
+ <library>comdlg32</library>
+ <file>audio_format.cpp</file>
+ <file>audio_membuffer.cpp</file>
+ <file>audio_producer.cpp</file>
+ <file>audio_receiver.cpp</file>
+ <file>audio_resampler_acm.cpp</file>
+ <file>audio_wavein.cpp</file>
+ <file>audio_waveout.cpp</file>
+ <file>sndrec32.cpp</file>
+ <file>sndrec32.rc</file>
+</module>
--- /dev/null
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Italiano (Italia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
+#ifdef _WIN32
+LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_REACTOS_SNDREC32LL ICON "reactOS_sndrec32.ico"
+IDI_SMALL ICON "small.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDC_REACTOS_SNDREC32 ACCELERATORS
+BEGIN
+ "?", IDM_ABOUT, ASCII, ALT
+ "/", IDM_ABOUT, ASCII, ALT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 196, 75
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Informazioni su reactOS_sndrec32"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ ICON 128,IDC_REACTOS_SNDREC32,19,14,21,20
+ LTEXT "reactOS_sndrec32, versione 1.0",IDC_STATIC,56,16,114,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 2009",IDC_STATIC,55,25,114,8
+ DEFPUSHBUTTON "OK",IDOK,139,54,50,14,WS_GROUP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 189
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 68
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#ifndef APSTUDIO_INVOKED\r\n"
+ "#include ""targetver.h""\r\n"
+ "#endif\r\n"
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_BITMAP2_START BITMAP "but_start.bmp"
+IDB_BITMAP2_END BITMAP "but_end.bmp"
+IDB_BITMAP2_PLAY BITMAP "but_play.bmp"
+IDB_BITMAP2_STOP BITMAP "but_stop.bmp"
+IDB_BITMAP2_REC BITMAP "but_rec.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU
+BEGIN
+ POPUP "File"
+ BEGIN
+ MENUITEM "New", ID_NEW
+ MENUITEM "Open...", ID_FILE_OPEN
+ MENUITEM "Save", ID_FILE_SAVE, GRAYED
+ MENUITEM "Save As...", ID_FILE_SAVEAS
+ MENUITEM SEPARATOR
+ MENUITEM "Exit", ID_EXIT
+ END
+ MENUITEM "todo1", 0
+ MENUITEM "todo2", 0
+ POPUP "?"
+ BEGIN
+ MENUITEM "About...", ID__ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_APP_TITLE "reactOS_sndrec32"
+ IDC_REACTOS_SNDREC32 "REACTOS_SNDREC32"
+END
+
+#endif // Italiano (Italia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
--- /dev/null
+// stdafx.h : file di inclusione per file di inclusione di sistema standard
+// o file di inclusione specifici del progetto utilizzati di frequente, ma
+// modificati raramente
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Escludere gli elementi utilizzati di rado dalle intestazioni di Windows
+// File di intestazione di Windows:
+#include <windows.h>
+#include <commctrl.h>
+#include <Commdlg.h>
+
+// File di intestazione Runtime C
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <tchar.h>
+
+
+// TODO: fare riferimento qui alle intestazioni aggiuntive richieste dal programma
--- /dev/null
+#pragma once
+
+// Le macro seguenti definiscono la piattaforma minima richiesta. La piattaforma minima richiesta
+// è costituita dalla versione meno recente di Windows, Internet Explorer e così via contenenti le funzionalità necessarie per eseguire
+// l'applicazione. Le macro consentono di attivare tutte le funzionalità disponibili nelle versioni delle piattaforme fino
+// alla versione specificata compresa.
+
+// Modificare le seguenti definizioni se è necessario utilizzare come destinazione una piattaforma prima di quelle specificate di seguito.
+// Fare riferimento a MSDN per informazioni aggiornate sui valori corrispondenti per le differenti piattaforme.
+#ifndef WINVER // Specifica che la piattaforma minima richiesta è Windows Vista.
+#define WINVER 0x0600 // Modificare il valore con quello appropriato per altre versioni di Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Specifica che la piattaforma minima richiesta è Windows Vista.
+#define _WIN32_WINNT 0x0600 // Modificare il valore con quello appropriato per altre versioni di Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Specifica che la piattaforma minima richiesta è Windows 98.
+#define _WIN32_WINDOWS 0x0410 // Modificare il valore con quello appropriato per Windows Me o versioni successive.
+#endif
+
+#ifndef _WIN32_IE // Specifica che la piattaforma minima richiesta è Internet Explorer 7.0.
+#define _WIN32_IE 0x0700 // Modificare il valore con quello appropriato per altre versioni di IE.
+#endif