Howdy, Stranger!

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

Categories

Capturing Mic input from sound card using directsound

ahabdulleahabdulle Member Posts: 1
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.