1
Reply

capturing sound using directx and c# to a wave file

forsaleh

forsaleh

May 14 2004 2:20 PM
5.8k
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"; } } }

Answers (1)