Csharp: Sound recording, csharprecording

Source: Internet
Author: User

Csharp: Sound recording, csharprecording

Using System; using System. collections. generic; using System. linq; using System. text; using Microsoft. directX; using Microsoft. directX. directSound; using System. IO; using System. threading; using System. data; using System. drawing; using System. windows. forms; namespace AudioBaiduDemo {/// <summary> /// DirectSound recording /// http://blog.csdn.net/woaixiaozhe/article/details/7852824/ /// </Summary> public class SoundRecorder {# region member data private Capture mCapDev = null; // audio capturing device private CaptureBuffer mRecBuffer = null; // buffer object private WaveFormat mWavFormat; // The recording format is private int mNextCaptureOffset = 0; // the starting point of the recording buffer zone is private int mSampleCount = 0; // The number of recording samples is private Notify mNotify = null; // Message notification object public const int cNotifyNum = 16; // number of notifications private int mNotifySize = 0; // each notification Size private int mBufferSize = 0; // Buffer Queue size private Thread myythread = null; // the Thread that processes the buffer message private AutoResetEvent mNotificationEvent = null; // notification event private string mFileName = string. empty; // file storage path private FileStream mWaveFile = null; // file stream private BinaryWriter mWriter = null; // write the file # endregion # region external operation function // <summary> // constructor to set the recording device and recording format. /// <summary> public SoundRecorder () {// initialize the sound Frequency capturing device InitCaptureDevice (); // sets the recording format mWavFormat = CreateWaveFormat () ;}/// <summary> // creates the recording format, where 16bit, 16 KHz, mono recording format // <summary> private WaveFormat CreateWaveFormat () {Microsoft. directX. directSound. waveFormat format = new Microsoft. directX. directSound. waveFormat ();//. waveFormat (); format. formatTag = WaveFormatTag. pcm; // PCM format. samplesPerSecond = 16000; // sampling rate: 16 KHz format. bitsPerSamp Le = 16; // number of sampling digits: 16 bit format. channels = 1; // audio channel: Mono format. blockAlign = (short) (format. channels * (format. bitsPerSample/8); // The number of bytes in the unit of sample points format. averageBytesPerSecond = format. blockAlign * format. samplesPerSecond; return format; // according to the above sampling specifications, we can see that the number of bytes for one second is 16000*2 = 32000B is about 31 K} // <summary> // sets the file to be saved after the recording ends, including path /// </summary> /// <param name = "filename"> Save the path name of the wav file </param> public void SetFileN Ame (string filename) {mFileName = filename;} // <summary> // start recording /// </summary> public void RecStart () {// create a recording file CreateSoundFile (); // create a recording buffer and start recording CreateCaptureBuffer (); // create a notification message, when the buffer is full, the processing method is InitNotifications (); mRecBuffer. start (true) ;}/// <summary> // stop the recording /// </summary> public void RecStop () {mRecBuffer. stop (); // call the Stop method of the buffer to Stop collecting sound if (null! = MNotificationEvent) mNotificationEvent. set (); // disable mpolicythread. abort (); // The end thread RecordCapturedData (); // write the last part of the buffer to the file. // write the mWriter at the end of the WAV file. seek (4, SeekOrigin. begin); mWriter. write (int) (mSampleCount + 36); // Write the length of the file mWriter. seek (40, SeekOrigin. begin); mWriter. write (mSampleCount); // Write Data Length mWriter. close (); mWaveFile. close (); mWriter = null; mWaveFile = null; }# endregion # region internal operation function // <Summary> // initialize the recording device. The main recording device is used here. /// </summary> /// <returns> returns true if the call is successful. Otherwise, false is returned. </returns> private bool InitCaptureDevice () {// obtain the default audio capturing device CaptureDevicesCollection devices = new CaptureDevicesCollection (); // enumerate the Guid deviceGuid = Guid of the audio capturing device. empty; if (devices. count> 0) deviceGuid = devices [0]. driverGuid; else {MessageBox. show ("no audio capturing device in the system"); return false;} // create a Capture object with the specified capturing device try {mCapDev = New Capture (deviceGuid);} catch (DirectXException e) {MessageBox. show (e. toString (); return false;} return true;} // <summary> // create the buffer used for recording. // </summary> private void CreateCaptureBuffer () {// description object of the buffer zone Microsoft. directX. directSound. captureBufferDescription bufferdescription = new Microsoft. directX. directSound. captureBufferDescription (); if (null! = MNotify) {mNotify. Dispose (); mNotify = null;} if (null! = MRecBuffer) {mRecBuffer. Dispose (); mRecBuffer = null;} // set the notification size. The default value is 1 s mpolicysize = (1024> mWavFormat. AverageBytesPerSecond/8 )? 1024: (mWavFormat. averageBytesPerSecond/8); mpolicysize-= mpolicysize % mWavFormat. blockAlign; // set the buffer size mBufferSize = mNotifySize * cpolicynum; // create a buffer description bufferdescription. bufferBytes = mBufferSize; bufferdescription. format = mWavFormat; // recording Format // create a buffer mRecBuffer = new CaptureBuffer (bufferdescription, mCapDev); mNextCaptureOffset = 0 ;}/// <summary> /// initialize a notification event, divide the original buffer into 16 buffer queues and set a notification point at the end of each Buffer Queue. /// </summary> /// <returns> whether the private bool InitNotifications () {if (null = mRecBuffer) {MessageBox. show ("Recording buffer not created"); return false;} // create a notification event. When the Buffer Queue is full, this event is triggered. micationicationevent = new AutoResetEvent (false); // create a Thread to manage the buffer event if (null = myythread) {mNotifyThread = new Thread (new ThreadStart (WaitThread); mNotifyThread. start () ;}// set the notification location BufferPositionNotify [] PositionNotify = new BufferPositionNotify [cpolicynum + 1]; for (int I = 0; I <cpolicynum; I ++) {positionpolicy [I]. offset = (mpolicysize * I) + mpolicysize-1; positionpolicy [I]. eventpolicyhandle = mNotificationEvent. safeWaitHandle. dangerousGetHandle ();} My y = new Notify (mRecBuffer); mNotify. setnotifposipositions (PositionNotify, cNotifyNum); return true ;}/// <summary> // processing thread that receives messages in the buffer zone that are full /// </summary> private void WaitThread () {while (true) {// wait for the notification message mNotificationEvent in the buffer zone. waitOne (Timeout. infinite, true); // RecordCapturedData ();}} /// <summary> /// write the recorded data to a wav file /// </summary> private void RecordCapturedData () {byte [] CaptureData = null; int ReadPos = 0, CapturePos = 0, LockSize = 0; mRecBuffer. getCurrentPosition (out CapturePos, out ReadPos); LockSize = ReadPos-mNextCaptureOffset; if (LockSize <0) // because it is a circular buffer, there is a negative case: when the text returns to the first notification point with the read pointer, while Ibuffeoffset is still in the last notification location LockSize + = mBufferSize; LockSize-= (LockSize % mNotifySize); // alignment the buffer boundary, in fact, this operation is redundant because the configuration is complete. if (0 = LockSize) return; // read the data in the buffer zone CaptureData = (byte []) mRecBuffer. read (mNextCaptureOffset, typeof (byte), LockFlag. none, LockSize); // write the Wav file mWriter. write (CaptureData, 0, CaptureData. length); // update the recorded data Length. mSampleCount + = CaptureData. length; // the starting point of the mobile recording data. The notification message is only used to indicate the location where the message was generated and does not record the location of the previous recording. mNextCaptureOffset + = CaptureData. length; mNextCaptureOffset % = mBufferSize; // Circular buffer} // <summary> // create a saved waveform file and write the necessary file header. /// </summary> private void CreateSoundFile () {// Open up the wave file for writing. mWaveFile = new FileStream (mFileName, FileMode. create); mWriter = new BinaryWriter (mWaveFile ); /*************************************** * ********************************** Here is where the file will be created. A wave file is a RIFF file, which has chunks of data that describe what the file contains. A wave RIFF file is put together like this: The 12 byte RIFF chunk is constructed like this: Bytes 0-3: 'r'' I 'f''f'bytes 4-7: Length of file, minus the first 8 Bytes of the RIFF description. (4 bytes for "WAVE" + 24 bytes for format chunk length + 8 bytes for data chunk description + actual sample data size .) bytes 8-11: 'w'' A ''v'' E 'The 24 byte FORMAT chunk is constructed like this: Bytes 0-3: 'f''m'' ''Bytes 4-7: The format chunk length. this is always 16. bytes 8-9: File padding. always 1. bytes 10-11: Number of channels. either 1 for mono, or 2 for stereo. bytes 12-15: Sample rate. bytes 16-19: Number of bytes per second. bytes 20-21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or 16 bit mono, 4 for 16 bit stereo. bytes 22-23: Number of bits per sample. the DATA chunk is constructed like this: Bytes 0-3: 'D' a' 't'a' Bytes 4-7: Length of data, in bytes. bytes 8-: Actual sample data. **************************************** ********************************** // Set up file with RIFF chunk info. char [] ChunkRiff = {'R', 'I', 'F', 'F'}; char [] ChunkType = {'w', 'A ', 'V', 'E'}; char [] ChunkFmt = {'F', 'M','t ',''}; char [] ChunkData = {'D', 'A', 't', 'A'}; short shPad = 1; // File padding int nFormatChunkLength = 0x10; // Format chunk length. int nLength = 0; // File length, minus first 8 bytes of RIFF description. this will be filled in later. short shBytesPerSample = 0; // Bytes per sample. // The number of bytes of a sample point if (8 = mWavFormat. bitsPerSample & 1 = mWavFormat. channels) shBytesPerSample = 1; else if (8 = mWavFormat. bitsPerSample & 2 = mWavFormat. channels) | (16 = mWavFormat. bitsPerSample & 1 = mWavFormat. channels) shBytesPerSample = 2; else if (16 = mWavFormat. bitsPerSample & 2 = mWavFormat. channels) shBytesPerSample = 4; // RIFF block mWriter. write (ChunkRiff); mWriter. write (nLength); mWriter. write (ChunkType); // WAVE block mWriter. write (ChunkFmt); mWriter. write (nFormatChunkLength); mWriter. write (shPad); mWriter. write (mWavFormat. channels); mWriter. write (mWavFormat. samplesPerSecond); mWriter. write (mWavFormat. averageBytesPerSecond); mWriter. write (shBytesPerSample); mWriter. write (mWavFormat. bitsPerSample); // data block mWriter. write (ChunkData); mWriter. write (int) 0); // The sample length will be written in later .} # endregion }}

Test:

/// <Summary> ///// </summary> public partial class Form4: Form {private SoundRecorder recorder = null; // recording string wavfile = ""; /// <summary> ///// </summary> public Form4 () {InitializeComponent (); recorder = new SoundRecorder ();} /// <summary> //// </summary> /// <param name = "sender"> </param> /// <param name = "e "> </param> private void Form4_Load (object sender, eventArgs e) {}/// <summary> /// recording settings /// </summary> /// <param name = "sender"> </param> /// <param name = "e"> </param> private void button2_Click (object sender, eventArgs e) {string wavfile = null; wavfile = "test.wav"; recorder. setFileName (wavfile); recorder. recStart ();} /// <summary> /// stop /// </summary> /// <param name = "sender"> </param> /// <param name =" e "> </param> private void button3_Click (object sender, eventArgs e) {recorder. recStop (); recorder = null ;}

  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.