Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Capturing Mic input from sound card using directsound

ahabdulleahabdulle Posts: 1Member
Hallo,

I am working on a project to develop a software defined radio.
I am an engineer with very limited programming experience.
My first step is to familiarise with directx, I wanted to write a program to capture sound coming in from the line input of the soundcard (Mic) using directsound and display it or even just save it to a file. I have got a few ideas online and few sample codes. Below is the code i have been working with but it doesnt seem to work.

Kindly help



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.DirectSound;
using Microsoft.DirectX;
using Buffer = Microsoft.DirectX.DirectSound.Buffer;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;

namespace ARAMC
{
public partial class ATISRecordPanel : Form
{
string tempFile = "C:\Program Files\ARAMC\Temp.WAV";
private Capture MyCapture = new Capture();
private CaptureBuffer MySndBuf;
///
/// Sets a default format capture buffer with no effects; 22KHz 8bit/sample, mono
///
public ATISRecordPanel()
{
InitializeComponent();
CaptureBufferDescription MySBufDesc = 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
MySBufDesc.Format = DefaultFormat;
MySBufDesc.BufferBytes = 100000;
MySBufDesc.ControlEffects = false;
MySBufDesc.WaveMapped = true;

MySndBuf = new CaptureBuffer(MySBufDesc, MyCapture);
}

///
/// Constructor that sets format and buffersize, as well as enables
/// echo cancellation and noise suppression effects
///
///
///

public void SoundRec(WaveFormat MyFormat, int bufsize)
{
CaptureBufferDescription MySBufDesc = new CaptureBufferDescription();
//Format has been defined in MainForm
MySBufDesc.Format = MyFormat;
MySBufDesc.BufferBytes = bufsize;
MySBufDesc.ControlEffects = true;
MySBufDesc.WaveMapped = true;

// CaptureAcousticEchoCancellationEffect AECEffect;
//
// MySBufDesc.CaptureEffectDescription = new CaptureEffectDescription[1];
// MySBufDesc.CaptureEffectDescription[0].LocateInSoftware = true;
// MySBufDesc.CaptureEffectDescription[0].GuidEffectsClass = DSoundHelper.CaptureEffectsMsAcousticEchoCancellation;
// MySBufDesc.CaptureEffectDescription[0].GuidEffectsInstance = DSoundHelper.InterfaceCaptureEffectsAcousticEchoCancellation;
// MySBufDesc.CaptureEffectDescription[1].LocateInSoftware = true;
// MySBufDesc.CaptureEffectDescription[1].GuidEffectsClass = DSoundHelper.CaptureEffectsMsNoiseSuppression;

try
{
//Create the CaptureBuffer
MySndBuf = new CaptureBuffer(MySBufDesc,MyCapture);
}
catch (SoundException se)
{
MessageBox.Show( "There is a " + se.ErrorString +
" sound exception", "DirectSound Error");
}
}
///
/// Starts the capture from the capture device
///
public void StartRecord()
{
MySndBuf.Start(true);
}

///
/// Stops the recording of sound.
///
public void StopRecord()
{
MySndBuf.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();
MySndBuf.GetCurrentPosition(out writeposition, out readposition);
MySndBuf.Read(0, MemStream, writeposition, LockFlag.None);
Stream MyStream = new FileStream(tempFile, 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(MySndBuf.Format.Channels, 2));
byteArrayList.AddRange( ToBytes(MySndBuf.Format.SamplesPerSecond, 4));
byteArrayList.AddRange( ToBytes(MySndBuf.Format.AverageBytesPerSecond, 4));
byteArrayList.AddRange( ToBytes(MySndBuf.Format.BlockAlign, 2));
byteArrayList.AddRange( ToBytes(MySndBuf.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:
" + ae.Message);
}
finally
{
MemStream.Close();
MyStream.Close();
}


}

///
/// returns capture status (boolean)
///
///
public bool Capturing()
{
return MySndBuf.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;
}
}

public void RecordATIS(string ATIS)
{
textBox1.Text = ATIS;
}

private void RecordButton_CheckedChanged(object sender, EventArgs e)
{
if (RecordButton.Checked == true)
{
StartRecord();
}
else
{
StopRecord();
}
}

private void SaveButton_CheckedChanged(object sender, EventArgs e)
{
SaveButton.Checked = false;
ReadData();
}

private void ListenButton_CheckedChanged(object sender, EventArgs e)
{
if (ListenButton.Checked == true)
{
PlaySound(tempFile, IntPtr.Zero,
SoundFlags.SND_FILENAME | SoundFlags.SND_ASYNC);
}
else
{
PlaySound(null, IntPtr.Zero, SoundFlags.SND_PURGE);
}
}

[DllImport("winmm.dll", SetLastError = true,
CallingConvention = CallingConvention.Winapi)]
static extern bool PlaySound(
string pszSound,
IntPtr hMod,
SoundFlags sf);

// Flags for playing sounds. For this example, we are reading

// the sound from a filename, so we need only specify

// SND_FILENAME | SND_ASYNC

[Flags]

public enum SoundFlags : int
{
SND_SYNC = 0x0000, // play synchronously (default)

SND_ASYNC = 0x0001, // play asynchronously

SND_NODEFAULT = 0x0002, // silence (!default) if sound not found

SND_MEMORY = 0x0004, // pszSound points to a memory file

SND_LOOP = 0x0008, // loop the sound until next sndPlaySound

SND_NOSTOP = 0x0010, // don't stop any currently playing sound

SND_NOWAIT = 0x00002000, // don't wait if the driver is busy

SND_ALIAS = 0x00010000, // name is a registry alias

SND_ALIAS_ID = 0x00110000, // alias is a predefined ID

SND_FILENAME = 0x00020000, // name is file name

SND_RESOURCE = 0x00040004, // name is resource name or atom

SND_PURGE = 0x0040,

SND_APPLICATION = 0x0080

}
}
}

Sign In or Register to comment.