Tutorials to .com

Tutorials to .com » Dotnet » Control-and-components » C # in the use of DirectSound audio

C # in the use of DirectSound audio

Print View , by: iSee ,Total views: 27 ,Word Count: 3241 ,Date: Fri, 22 May 2009 Time: 10:35 AM

1. The basic principles of recording sound card

In order to achieve a basic process of recording, at least the support of the following objects:

1. Recording equipment, our equipment is the PC sound card. The recording equipment can be the beginning of the operation and closure.

2. The buffer zone, which is recording the voice on the question of where.



. DirectSound for audio description of the model

1. DirectSound recording support for categories

Capture, device object can be described as a sound card.

CaptureBuffer, buffer objects, storage of audio data input.

Notify, event notification, and since recording process is a long time, so the use of a buffer queue (number of buffer) to receive data, a buffer zone when the time expires, the system use this object to inform the application of the buffer zone removed and to continue recording.

These three objects is the main target of the operation of sound recording, as in c + + in the operation of the DirectSound of DirectX help files have a very detailed description will not repeat here. This article is for Managed Code. In addition to the above three main categories of DirectSound, but also need the following helper class.

WaveFormat, record describes the format of the voice waveform, such as sample rate, mono or stereo, the length of each sampling point and so on.

Thread, thread type, as the recording process is the need to continue to deal with the events over the buffer zone, so create a new thread to deal with this separately.

AutoResetEvent, notice of the incident, when the buffer over time, use the event as a notification event.



. Code analysis (SoundRecord category)

1. Need to invoke the procedures set

using System;

using System.Windows.Forms;

using System.Threading;

using System.IO;



/ / Support for DirectSound

using Microsoft.DirectX;

using Microsoft.DirectX.DirectSound;



2. Members of SoundRecord data

public const int cNotifyNum = 16; / / buffer the number of queue



private int mNextCaptureOffset = 0; / / The starting point for recording the buffer zone

private int mSampleCount = 0; / / record the number of samples



private int mNotifySize = 0; / / notice the size of each

private int mBufferSize = 0; / / buffer queue size



private string mFileName = string.Empty; / / File Name

private FileStream mWaveFile = null; / / file stream

private BinaryWriter mWriter = null; / / write file



private Capture mCapDev = null; / / audio capture device

private CaptureBuffer mRecBuffer = null; / / buffer object

private Notify mNotify = null; / / message to inform the target



private WaveFormat mWavFormat; / / audio format

private Thread mNotifyThread = null; / / buffer message processing thread

private AutoResetEvent mNotificationEvent = null; / / notification events



3. A function of external operations

/ / / <summary>

/ / / Constructor function, set the recording equipment, set the recording format.

/ / / </ Summary>

public SoundRecord ()

(

/ / Initialize the audio capture device

InitCaptureDevice ();



/ / Set the recording format

mWavFormat = CreateWaveFormat ();

)



/ / / <summary>

/ / / Set the recording after the end of the saved file, including path

/ / / </ Summary>

/ / / <param Name="filename"> save wav file path name </ param>

public void SetFileName (string filename)

(

mFileName = filename;

)



/ / / <summary>

/ / / Beginning of sound recording

/ / / </ Summary>

public void RecStart ()

(

/ / Create a sound file

CreateSoundFile ();



/ / Create a sound buffer, and begin recording

CreateCaptureBuffer ();



/ / Establish a notification message, when the buffer approaches full time

InitNotifications ();



mRecBuffer.Start (true);

)



/ / / <summary>

/ / / Stop recording

/ / / </ Summary>

public void RecStop ()

(

/ / Close the notification message

if (null! = mNotificationEvent)

mNotificationEvent.Set ();



/ / Stop recording

mRecBuffer.Stop ();



/ / Write the last data buffer

RecordCapturedData ();

/ / Write-back length of the information

mWriter.Seek (4, SeekOrigin.Begin);

mWriter.Write ((int) (mSampleCount + 36)); / / write the length of documents

mWriter.Seek (40, SeekOrigin.Begin);

mWriter.Write (mSampleCount); / / write data length

mWriter.Close ();

mWaveFile.Close ();

mWriter = null;

mWaveFile = null;

)



4. Internal call functions

/ / / <summary>

/ / / Initialize the recording equipment, where the main use of recording equipment.

/ / / </ Summary>

/ / / <returns> Call successful return true, otherwise return false </ returns>

private bool InitCaptureDevice ()

(

/ / access to the default audio capture device

CaptureDevicesCollection devices = new CaptureDevicesCollection (); / / enumerate the audio capture device

Guid deviceGuid = Guid.Empty; / / audio capture device ID



if (devices.Count> 0)

deviceGuid = devices [0]. DriverGuid;

else

(

MessageBox.Show ( "system there is no audio capture device");

return false;

)



/ / Capture device with the specified object to create Capture

try

(

mCapDev = new Capture (deviceGuid);

)

catch (DirectXException e)

(

MessageBox.Show (e.ToString ());

return false;

)



return true;

)



/ / / <summary>

/ / / Create a sound recording format, where the use of 16bit, 16KHz, Mono recording format

/ / / </ Summary>

/ / / <returns> WaveFormat structure </ returns>

private WaveFormat CreateWaveFormat ()

(

WaveFormat format = new WaveFormat ();



format.FormatTag = WaveFormatTag.Pcm; / / PCM

format.SamplesPerSecond = 16000; / / 16KHz

format.BitsPerSample = 16; / / 16Bit

format.Channels = 1; / / Mono

format.BlockAlign = (short) (format.Channels * (format.BitsPerSample / 8));

format.AverageBytesPerSecond = format.BlockAlign * format.SamplesPerSecond;



return format;

)



/ / / <summary>

/ / / Create a sound recording used in the buffer zone

/ / / </ Summary>

private void CreateCaptureBuffer ()

(

/ / Buffer object to describe

CaptureBufferDescription bufferdescription = new CaptureBufferDescription ();



if (null! = mNotify)

(

mNotify.Dispose ();

mNotify = null;

)

if (null! = mRecBuffer)

(

mRecBuffer.Dispose ();

mRecBuffer = null;

)



/ / Set to inform the size, the default clock for the 1s

mNotifySize = (1024> mWavFormat.AverageBytesPerSecond / 8)? 1024: (mWavFormat.AverageBytesPerSecond / 8);

mNotifySize -= mNotifySize% mWavFormat.BlockAlign;



/ / Set the buffer size

mBufferSize = mNotifySize * cNotifyNum;



/ / Create a buffer description

bufferdescription.BufferBytes = mBufferSize;

bufferdescription.Format = mWavFormat; / / audio format



/ / Create a buffer zone

mRecBuffer = new CaptureBuffer (bufferdescription, mCapDev);



mNextCaptureOffset = 0;

)



/ / / <summary>

/ / / Initialize the notification event, the original buffer into the buffer queue 16 in each end of the buffer queue to inform the point of setting.

/ / / </ Summary>

/ / / <returns> Success </ returns>

private bool InitNotifications ()

(

if (null == mRecBuffer)

(

MessageBox.Show ( "not create a sound buffer");

return false;

)



/ / Create a notification event, when the buffer queue is full on the excitation of the incident.

mNotificationEvent = new AutoResetEvent (false);



/ / Create a buffer zone incident management thread

if (null == mNotifyThread)

(

mNotifyThread = new Thread (new ThreadStart (WaitThread));

mNotifyThread.Start ();

)



/ / Set to inform the location of

BufferPositionNotify [] PositionNotify = new BufferPositionNotify [cNotifyNum + 1];

for (int i = 0; i <cNotifyNum; i + +)

(

PositionNotify [i]. Offset = (mNotifySize * i) + mNotifySize - 1;

PositionNotify [i]. EventNotifyHandle = mNotificationEvent.Handle;

)



mNotify = new Notify (mRecBuffer);

mNotify.SetNotificationPositions (PositionNotify, cNotifyNum);



return true;

)



/ / / <summary>

/ / / The data will be written into the wav recording file

/ / / </ Summary>

private void RecordCapturedData ()

(

byte [] CaptureData = null;

int ReadPos;

int CapturePos;

int LockSize;



mRecBuffer.GetCurrentPosition (out CapturePos, out ReadPos);

LockSize = ReadPos - mNextCaptureOffset;

if (LockSize <0)

LockSize + = mBufferSize;



/ / Align the buffer zone boundary, in fact, it started to complete as a result of this operation is redundant.

LockSize -= (LockSize% mNotifySize);



if (0 == LockSize)

return;

/ / Read data buffer

CaptureData = (byte []) mRecBuffer.Read (mNextCaptureOffset, typeof (byte), LockFlag.None, LockSize);



/ / Write Wav files

mWriter.Write (CaptureData, 0, CaptureData.Length);



/ / Update the data length has been recorded.

mSampleCount + = CaptureData.Length;



/ / Move the starting point of recording data to inform the message source is responsible only for the location of the instructions have not recorded the location of the last record

mNextCaptureOffset + = CaptureData.Length;

mNextCaptureOffset% = mBufferSize; / / Circular buffer

)



/ / / <summary>

/ / / Receive buffer full message handling thread

/ / / </ Summary>

private void WaitThread ()

(

while (true)

(

/ / Wait for the notification message buffer

mNotificationEvent.WaitOne (Timeout.Infinite, true);

/ / Record data

RecordCapturedData ();

)

)



/ / / <summary>

/ / / Create a stored waveform file and writes the necessary files first.

/ / / </ Summary>

private void CreateSoundFile ()

(

/************************************************* *************************

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' 't' ''

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.

************************************************** *************************/

/ / Open up the wave file for writing.

mWaveFile = new FileStream (mFileName, FileMode.Create);

mWriter = new BinaryWriter (mWaveFile);



/ / 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.



/ / One byte of the number of sample points

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 blocks

mWriter.Write (ChunkData);

mWriter.Write ((int) 0); / / The sample length will be written in later.

)



5. Way to call external form

Statement in part:

private SoundRecord recorder = null; / / recording

Form constructor:

recorder = new SoundRecord ();

Button to start recording:

private void btnStart_Click (object sender, System.EventArgs e)

(

/ /

/ / Audio settings

/ /

string wavfile = null;

wavfile = "test.wav";

recorder.SetFileName (wavfile);

recorder.RecStart ();

)

Button to suspend recording:

private void btnStop_Click (object sender, System.EventArgs e)

(

recorder.RecStop ();

recorder = null;

)



6. Need to add an external reference file

In the system under the System32 directory, add the following two reference documents, and if not, in the development of DirectX can be found inside the package.

Microsoft.DirectX.dll

Microsoft.DirectX.DirectSound.dll


.Net Control and components Articles


Can't Find What You're Looking For?


Rating: Not yet rated

Comments

No comments posted.