I have used a code from the tek tips forum for recording sound in c#
and it is great code. I'm new in the sound programming and I have no background in
this field except that I know c# and also some classes in Microsoft.Directx namespace
that deals with recording sound like CreateBuffer class. I have changed the code
so that it has GUI. It can produe sound file, but when it is played I hear only chuk
at beginning and at the end. If any any one knows how to solve this problem it would be appreciated if he/she post it.
regards
here is the source code
/******************************************************************************
* Class Name: SoundRec
* Purpose: Primitive Sound Capture Class for Managed DirectX 9.0 C#.Net
* Description: This Class uses the CaptureBuffer Class
* to capture sounds from the default system device
* and saves it in the file name test.wav. You will need
* to modifify it for your purposes. Hope anyone who uses
* This class can have an easier time learning how to use
* M.DirectX.DirectSound than I did! Have Fun!!
*
* You may not: Alter any part of this comment, however you may add
* on new comments if you have improved on it.
* Original Author: Nicholas Wong (Jan 2004)
* email:
[email protected]
*
*****************************************************************************/
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX.AudioVideoPlayback;
using Microsoft.DirectX.DirectSound;
using System.IO;
// Avoid name collision with System.Buffer
using Buffer = Microsoft.DirectX.DirectSound.Buffer;
namespace TryingAudio
{
///
/// Summary description for Form1.
///
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btnRecord;
//++++++++++++++++++++++
Capture capture;
CaptureBufferDescription capDesc;
CaptureBuffer capBuff;
private System.Windows.Forms.Button btnStop;
//++++++++++++++++++++++
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
//------------------------------------
capture = new Capture();
capDesc = new CaptureBufferDescription();
//setting the default wave capture format for use
//by the buffer descriptor
WaveFormat DefaultFormat = new WaveFormat();
DefaultFormat.SamplesPerSecond = 22000; //default freq 22khz
DefaultFormat.Channels = 1;
DefaultFormat.BitsPerSample = 8;
DefaultFormat.AverageBytesPerSecond = 22000;
DefaultFormat.BlockAlign = 1;
//setting the buffer descriptor to tell the capture buffer object how the
//buffer should perform
capDesc.Format = DefaultFormat;
capDesc.BufferBytes = 100000;
capDesc.ControlEffects = true;
capDesc.WaveMapped = true;
capBuff = new CaptureBuffer(capDesc,capture);
//------------------------------------
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.btnRecord = new System.Windows.Forms.Button();
this.btnStop = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(32, 24);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(368, 160);
this.label1.TabIndex = 0;
this.label1.Text = "Record:";
//
// btnRecord
//
this.btnRecord.Location = new System.Drawing.Point(416, 16);
this.btnRecord.Name = "btnRecord";
this.btnRecord.TabIndex = 1;
this.btnRecord.Text = "Record";
this.btnRecord.Click += new System.EventHandler(this.RecordClicked);
//
// btnStop
//
this.btnStop.Location = new System.Drawing.Point(416, 56);
this.btnStop.Name = "btnStop";
this.btnStop.Size = new System.Drawing.Size(80, 24);
this.btnStop.TabIndex = 2;
this.btnStop.Text = "Stop";
this.btnStop.Click += new System.EventHandler(this.StopClicked);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(512, 198);
this.Controls.Add(this.btnStop);
this.Controls.Add(this.btnRecord);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void RecordClicked(object sender, System.EventArgs e)
{
label1.Text += Capturing().ToString()+"RecordClicked\n";
StartRecord();
label1.Text += Capturing().ToString()+"\n";
}
//+++++++++++++++++++
///
/// Starts the capture from the capture device
///
public void StartRecord()
{
capBuff.Start(true);
}
///
/// Stops the recording of sound.
///
public void StopRecord()
{
capBuff.Stop();
}
///
/// Saves the data in the capture buffer into a wave file
///
public void ReadData()
{
int readposition, writeposition;
ArrayList byteArrayList = new ArrayList();
System.Text.ASCIIEncoding ascii = new System.Text.ASCIIEncoding();
//Create a new wav file to store the capture buffer data.
//if already exists will overwrite filename is test.wav
string path =Application.StartupPath + "\\test.wav";
Stream MemStream = new MemoryStream();
capBuff.GetCurrentPosition(out writeposition, out readposition);
capBuff.Read(0, MemStream, writeposition, LockFlag.None);
Stream MyStream = new FileStream(path, FileMode.Create);
//begin to write the wave file header. for more details
//Search google.com for "wave formats"
//RIFF header
try
{
byteArrayList.AddRange(ascii.GetBytes("RIFF"));
byteArrayList.AddRange( ToBytes(36 + (int)MemStream.Length, 4));
byteArrayList.AddRange(ascii.GetBytes("WAVE"));
//fmt chunk
byteArrayList.AddRange(ascii.GetBytes("fmt "));
//length of fmt chunk (never changes)
byteArrayList.AddRange( ToBytes(16, 4));
//"1" for pcm encoding
byteArrayList.AddRange( ToBytes(1, 2));
byteArrayList.AddRange( ToBytes(capBuff.Format.Channels, 2));
byteArrayList.AddRange( ToBytes(capBuff.Format.SamplesPerSecond, 4));
byteArrayList.AddRange( ToBytes(capBuff.Format.AverageBytesPerSecond, 4));
byteArrayList.AddRange( ToBytes(capBuff.Format.BlockAlign, 2));
byteArrayList.AddRange( ToBytes(capBuff.Format.BitsPerSample, 2));
//the data chunk
byteArrayList.AddRange(ascii.GetBytes("data"));
byteArrayList.AddRange( ToBytes((int)MemStream.Length, 4));
byte []buffer = new byte[MemStream.Length];
MemStream.Read(buffer, 0, (int)MemStream.Length);
byteArrayList.AddRange(buffer);
buffer = new byte[byteArrayList.Count];
byteArrayList.CopyTo(buffer);
MyStream.Write(buffer, 0, buffer.Length);
}
catch(ArgumentException ae)
{
MessageBox.Show("Argument Exception with Message:\n\t" + ae.Message);
}
finally
{
MemStream.Close();
MyStream.Close();
}
}
///
/// returns capture status (boolean)
///
///
public bool Capturing()
{
return capBuff.Capturing;
}
///
/// Recursive method that returns a target number in the form
/// of an ArrayList of bytes with designated number of bytes. If not enough
/// bytes to hold the targetnumber, will throw argumentexception.
/// Should be used in a try-catch clause
///
///
the value intended to convert
///
number of bytes needed
///
private ArrayList ToBytes(int targetnumber, short numofbytes)
{
int remainder, result;
ArrayList returningarray;
ArgumentException wrongnumofbytes =
new ArgumentException("Not enough bytes to represent number",
"numofbytes");
result = Math.DivRem(targetnumber, 256, out remainder);
//if not enough bytes specified to represent target number
if (targetnumber >= Math.Pow(256,(double)numofbytes))
{
throw wrongnumofbytes;
}
//if there are higher significant hexadecima, run a recursion
if (result >= 1)
{
returningarray = ToBytes(result, (short)(numofbytes-1));
returningarray.Insert(0, Convert.ToByte(remainder));
return returningarray;
}
else //if (result < 1) recursion terminating condition
{
returningarray = new ArrayList(numofbytes);
returningarray.Add(Convert.ToByte(targetnumber));
for (int i=0; i < numofbytes-1; i++)
{
returningarray.Add(Convert.ToByte(0));//fill up most significant hexadecima with 0's
}
return returningarray;
}
//++++++++++++++++++++
}
private void StopClicked(object sender, System.EventArgs e)
{
label1.Text += Capturing().ToString()+" StopClicked\n";
StopRecord();
ReadData();
label1.Text += Capturing().ToString()+"\n";
}
}
}