This is a program for recording sound from an Audio Input device.
I have taken help from the MSDN website ..... !
I did as they had mentioned ....
//wave.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace Record
{
public class wave
{
public const uint WAVE_MAPPER = unchecked((uint)(-1));
public const int CALLBACK_WINDOW = 0x10000;
private const int WAVERR_BASE = 32;
private const int MMSYSERR_BASE = 0;
public enum MMSYSERR : int
{
noerror = 0,
error = (MMSYSERR_BASE + 1),
bad_device_id = (MMSYSERR_BASE + 2),
not_enabled = (MMSYSERR_BASE + 3),
allocated = (MMSYSERR_BASE + 4),
inval_handle = (MMSYSERR_BASE + 5),
no_driver = (MMSYSERR_BASE + 6),
no_mem = (MMSYSERR_BASE + 7),
not_supported = (MMSYSERR_BASE + 8),
bad_error_num = (MMSYSERR_BASE + 9),
inval_flag = (MMSYSERR_BASE + 10),
inval_param = (MMSYSERR_BASE + 11),
handle_busy = (MMSYSERR_BASE + 12),
inval_alias = (MMSYSERR_BASE + 13),
baddb = (MMSYSERR_BASE + 14),
key_not_found = (MMSYSERR_BASE + 15),
read_error = (MMSYSERR_BASE + 16),
write_error = (MMSYSERR_BASE + 17),
del_error = (MMSYSERR_BASE + 18),
val_not_found = (MMSYSERR_BASE + 19),
no_drive_cb = (MMSYSERR_BASE + 20),
last_error = (MMSYSERR_BASE + 20)
}
public enum WAVERR : int
{
none = 0,
bad_format = (WAVERR_BASE + 1),
still_playing = (WAVERR_BASE + 2),
un_prepared = (WAVERR_BASE + 3),
sync = (WAVERR_BASE + 4),
last_error = (WAVERR_BASE + 5)
}
// Wave file formats !
public const uint wfi = 0x00000000; // Invalid Format
public const uint wf_1m08 = 0x00000001; //11.025 kHz, Mono, 8-bit
public const uint wf_1s08 = 0x00000002; //11.025 kHz, Stereo, 8-bit
public const uint wf_1m16 = 0x00000004; //11.025 kHz, Mono, 16-bit
public const uint wf_1s16 = 0x00000008; //11.025 kHz, Stereo, 16-bit
public const uint wf_2m08 = 0x00000010; //22.050 kHz, Mono, 8-bit
public const uint wf_2s08 = 0x00000020; //22.050 kHz, Stereo, 8-bit
public const uint wf_2m16 = 0x00000040; //22.050 kHz, Mono, 16-bit
public const uint wf_2s16 = 0x00000080; //22.050 kHz, Stereo, 16-bit
public const uint wf_4m08 = 0x00000100; //44.100 kHz, Mono, 8-bit
public const uint wf_4s08 = 0x00000200; //44.100 kHz, Stereo, 8-bit
public const uint wf_4m16 = 0x00000400; //44.100 kHz, Mono, 16-bit
public const uint wf_4s16 = 0x00000800; //44.100 kHz, Stereo, 16-bit
public class WAVEFORMATEX
{
protected const int WF_OFFSET_FORMATTAG = 20;
protected const int WF_OFFSET_CHANNELS = 22;
protected const int WF_OFFSET_SAMPLESPERSEC = 24;
protected const int WF_OFFSET_AVGBYTESPERSEC = 28;
protected const int WF_OFFSET_BLOCKALIGN = 32;
protected const int WF_OFFSET_BITSPERSAMPLE = 34;
public const int WF_OFFSET_DATA = 44;
public ushort wFormatTag = 0;
public ushort nChannels = 0;
public uint nSamplesPerSec = 0;
public uint nAvgBytesPerSec = 0;
public ushort nBlockAlign = 0;
public ushort wBitsPerSample = 0;
public void SeekTo(Stream fs)
{
fs.Seek(WF_OFFSET_FORMATTAG, SeekOrigin.Begin);
}
public void Skip(Stream fs)
{
fs.Seek(WF_OFFSET_DATA, SeekOrigin.Begin);
}
public void Read(BinaryReader rdr)
{
wFormatTag = rdr.ReadUInt16();
nChannels = rdr.ReadUInt16();
nSamplesPerSec = rdr.ReadUInt32();
nAvgBytesPerSec = rdr.ReadUInt32();
nBlockAlign = rdr.ReadUInt16();
wBitsPerSample = rdr.ReadUInt16();
uint dataId = rdr.ReadUInt32(),
dataLength = rdr.ReadUInt32();
}
public void Write(BinaryWriter wtr)
{
wtr.Write(wFormatTag);
wtr.Write(nChannels);
wtr.Write(nSamplesPerSec);
wtr.Write(nAvgBytesPerSec);
wtr.Write(nBlockAlign);
wtr.Write(wBitsPerSample);
}
}
public class WAVEHDR : IDisposable
{
public const int whdr_done = 0x00000001;
public const int whdr_prepared = 0x00000002;
public const int whdr_inloop = 0x00000004;
public const int whdr_endloop = 0x00000008;
public const int whdr_inq = 0x00000010;
public const int wf_PCM = 1;
public IntPtr lpData = IntPtr.Zero;
public uint dwBufferLength = 0;
public uint dwBytesRecorded = 0;
public uint dwUser = 0;
public uint dwFlags = 0;
public uint dwLoops = 0;
public IntPtr lpNext = IntPtr.Zero;
public uint reserved = 0;
public MMSYSERR Read(BinaryReader rdr, uint readLength, int align)
{
uint bufferLength = readLength;
if (bufferLength % align != 0)
bufferLength += (uint)(align - (bufferLength % align));
dwBufferLength = bufferLength;
byte[] data = new byte[readLength];
rdr.Read(data, 0, data.Length);
if (lpData == IntPtr.Zero)
lpData = Memory.LocalAlloc(Memory.LMEM_FIXED, (uint)bufferLength);
if (lpData == IntPtr.Zero)
return MMSYSERR.no_mem;
Marshal.Copy(data, 0, lpData, data.Length);
return MMSYSERR.noerror;
}
public wave.MMSYSERR Write(BinaryWriter wrtr)
{
if (lpData == IntPtr.Zero)
return wave.MMSYSERR.no_mem;
byte[] data = new byte[dwBytesRecorded];
Marshal.Copy(lpData, data, 0, data.Length);
wrtr.Write(data);
return wave.MMSYSERR.noerror;
}
public MMSYSERR Init(uint bufferLength, bool init)
{
if (lpData != IntPtr.Zero && dwBufferLength < bufferLength)
{
Memory.LocalFree(lpData);
lpData = IntPtr.Zero;
}
if (lpData == IntPtr.Zero)
lpData = Memory.LocalAlloc(Memory.LMEM_FIXED, bufferLength);
dwBufferLength = bufferLength;
if (lpData == IntPtr.Zero)
return MMSYSERR.no_mem;
if (init)
{
for (int i = 0; i < bufferLength; i++)
{
Marshal.WriteByte(lpData, i, 0);
}
}
return MMSYSERR.noerror;
}
public void Dispose()
{
if (lpData != IntPtr.Zero)
Memory.LocalFree(lpData);
}
}
}
}
In wave_in.cs, I got the following errors .... please help me correct them ...... ! :|
Error 1
The type or namespace name 'WindowsCE' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?) C:\Users\User\Documents\Visual Studio 2008\Projects\Record\Record\wave_in.cs 4 17 Record
Error 2
The type or namespace name 'Windows' does not exist in the namespace 'System' (are you missing an assembly reference?) C:\Users\User\Documents\Visual Studio 2008\Projects\Record\Record\wave_in.cs 9 14 Record
Error 3
The type or namespace name 'MessageWindow' could not be found (are you missing a using directive or an assembly reference?) C:\Users\User\Documents\Visual Studio 2008\Projects\Record\Record\wave_in.cs 298 46 Record
Error 4
The type or namespace name 'Message' could not be found (are you missing a using directive or an assembly reference?) C:\Users\User\Documents\Visual Studio 2008\Projects\Record\Record\wave_in.cs 312 49 Record
Error 5
The type or namespace name 'MainTest' could not be found (are you missing a using directive or an assembly reference?) C:\Users\User\Documents\Visual Studio 2008\Projects\Record\Record\wave_in.cs 506 37 Record
//wave_in.cs
using System;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.WindowsCE.Forms;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
namespace Record
{
public class wave_in
{
protected class WaveFile : IDisposable
{
protected IntPtr m_hwi = IntPtr.Zero;
protected wave.WAVEFORMATEX m_wfmt = null;
protected wave.WAVEHDR[] m_whdr = null;
protected bool m_inited = false;
protected int m_curBlock;
protected int m_numBlocks;
protected uint m_bufferSize;
protected uint m_maxDataLength;
public bool Done { get { return !m_recording; } }
protected bool m_recording = false;
public wave.MMSYSERR Preload(uint curDevice, IntPtr hwnd, int maxRecordLength_ms, int bufferSize)
{
// Do not allow recording to be interrupted
if (m_recording)
return wave.MMSYSERR.error;
// If this file is already initialized then start over
if (m_inited)
{
Stop();
FreeWaveBuffers();
}
// Create an instance of WAVEINCAPS to check if our desired
// format is supported
WAVEINCAPS caps = new WAVEINCAPS();
waveInGetDevCaps(0, caps, caps.Size);
if ((caps.dwFormats & wave.wf_1s08) == 0)
return wave.MMSYSERR.not_supported;
// Initialize a WAVEFORMATEX structure specifying the desired
// format
m_wfmt = new wave.WAVEFORMATEX();
m_wfmt.wFormatTag = wave.WAVEHDR.wf_PCM;
m_wfmt.wBitsPerSample = 8;
m_wfmt.nChannels = 2;
m_wfmt.nSamplesPerSec = 11025;
m_wfmt.nAvgBytesPerSec = (uint)(m_wfmt.nSamplesPerSec * m_wfmt.nChannels * (m_wfmt.wBitsPerSample / 8));
m_wfmt.nBlockAlign = (ushort)(m_wfmt.wBitsPerSample * m_wfmt.nChannels / 8);
// Attempt to open the specified device with the desired wave format
wave.MMSYSERR result = waveInOpen(ref m_hwi, curDevice, m_wfmt, hwnd, 0, wave.CALLBACK_WINDOW);
if (result != wave.MMSYSERR.noerror)
return result;
if (bufferSize == 0)
return wave.MMSYSERR.error;
m_bufferSize = (uint)bufferSize;
// Force the buffers to align to nBlockAlign
if (m_bufferSize % m_wfmt.nBlockAlign != 0)
m_bufferSize += m_wfmt.nBlockAlign - (m_bufferSize % m_wfmt.nBlockAlign);
// Determine the number of buffers needed to record the maximum length
m_maxDataLength = (uint)(m_wfmt.nAvgBytesPerSec * maxRecordLength_ms / 1000);
m_numBlocks = (int)(m_maxDataLength / m_bufferSize);
if (m_numBlocks * m_bufferSize < m_maxDataLength)
m_numBlocks++;
// Allocate the list of buffers
m_whdr = new wave.WAVEHDR[m_numBlocks + 1];
// Allocate and initialize two buffers to start with
m_whdr[0] = new wave.WAVEHDR();
m_whdr[1] = new wave.WAVEHDR();
result = InitBuffer(0);
if (result != wave.MMSYSERR.noerror)
return result;
result = InitBuffer(1);
if (result != wave.MMSYSERR.noerror)
return result;
m_curBlock = 0;
m_inited = true;
return wave.MMSYSERR.noerror;
}
public void BlockDone()
{
m_curBlock++;
// If the next block is not the padding buffer at the end of the
// recording then initialize another buffer, otherwise stop recording
if (m_curBlock < m_numBlocks)
{
InitBuffer(m_curBlock + 1);
}
else if (m_curBlock == m_numBlocks)
{
Stop();
}
}
public wave.MMSYSERR InitBuffer(int bufIndex)
{
// Determine the size of the buffer to create
uint writeLength = (uint)m_bufferSize;
if (bufIndex < m_numBlocks)
{
uint remainingDataLength = (uint)(m_maxDataLength - bufIndex * m_bufferSize);
if (m_bufferSize > remainingDataLength)
writeLength = remainingDataLength;
}
// If the header is not already instanced then instance it
if (m_whdr[bufIndex] == null)
m_whdr[bufIndex] = new wave.WAVEHDR();
// Allocate memory if not already allocated
wave.MMSYSERR result = m_whdr[bufIndex].Init(writeLength, false);
if (result != wave.MMSYSERR.noerror)
return result;
// Prepare the header
result = waveInPrepareHeader(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex]));
if (result != wave.MMSYSERR.noerror)
return result;
// Put the buffer in the queue
return waveInAddBuffer(m_hwi, m_whdr[bufIndex], (uint)Marshal.SizeOf(m_whdr[bufIndex]));
}
public wave.MMSYSERR Start()
{
if (!m_inited || m_recording)
return wave.MMSYSERR.error;
wave.MMSYSERR result = waveInStart(m_hwi);
if (result != wave.MMSYSERR.noerror)
return result;
m_recording = true;
return wave.MMSYSERR.noerror;
}
private void FreeWaveBuffers()
{
m_inited = false;
if (m_whdr != null)
{
for (int i = 0; i < m_whdr.Length; i++)
{
if (m_whdr[i] != null)
{
waveInUnprepareHeader(m_hwi, m_whdr[i], (uint)Marshal.SizeOf(m_whdr[i]));
m_whdr[i].Dispose();
m_whdr[i] = null;
}
}
m_whdr = null;
}
waveInClose(m_hwi);
m_hwi = IntPtr.Zero;
}
private void WriteChars(BinaryWriter wrtr, string text)
{
for (int i = 0; i < text.Length; i++)
{
char c = (char)text[i];
wrtr.Write(c);
}
}
public wave.MMSYSERR Save(string fileName)
{
if (!m_inited)
return wave.MMSYSERR.error;
if (m_recording)
Stop();
FileStream strm = null;
BinaryWriter wrtr = null;
try
{
if (File.Exists(fileName))
{
FileInfo fi = new FileInfo(fileName);
if ((fi.Attributes & FileAttributes.ReadOnly) != 0)
fi.Attributes -= FileAttributes.ReadOnly;
strm = new FileStream(fileName, FileMode.Truncate);
}
else
{
strm = new FileStream(fileName, FileMode.Create);
}
if (strm == null)
return wave.MMSYSERR.error;
wrtr = new BinaryWriter(strm);
if (wrtr == null)
return wave.MMSYSERR.error;
// Determine the size of the data, as the total number of bytes
// recorded by each buffer
uint totalSize = 0;
for (int i = 0; i < m_numBlocks; i++)
{
if (m_whdr[i] != null)
totalSize += m_whdr[i].dwBytesRecorded;
}
int chunkSize = (int)(36 + totalSize);
// Write out the header information
WriteChars(wrtr, "RIFF");
wrtr.Write(chunkSize);
WriteChars(wrtr, "WAVEfmt ");
wrtr.Write((int)16);
m_wfmt.Write(wrtr);
WriteChars(wrtr, "data");
wrtr.Write((int)totalSize);
// Write the data recorded to each buffer
for (int i = 0; i < m_numBlocks; i++)
{
if (m_whdr[i] != null)
{
wave.MMSYSERR result = m_whdr[i].Write(wrtr);
if (result != wave.MMSYSERR.noerror)
return result;
}
}
return wave.MMSYSERR.noerror;
}
finally
{
FreeWaveBuffers();
if (strm != null)
strm.Close();
if (wrtr != null)
wrtr.Close();
}
}
public void Stop()
{
waveInReset(m_hwi);
m_recording = false;
}
public void Dispose()
{
Stop();
FreeWaveBuffers();
}
}
protected class SoundMessageWindow : MessageWindow
{
public const int MM_WIM_OPEN = 0x3BE;
public const int MM_WIM_CLOSE = 0x3BF;
public const int MM_WIM_DATA = 0x3C0;
// Instance of a recording interface
protected wave_in m_wi = null;
public SoundMessageWindow(wave_in wi)
{
m_wi = wi;
}
protected override void WndProc(ref Message msg)
{
switch (msg.Msg)
{
// When this message is encountered, a block is
// done recording, so notify the WaveIn instance.
case MM_WIM_DATA:
{
if (m_wi != null)
m_wi.BlockDone();
}
break;
}
base.WndProc(ref msg);
}
}
protected SoundMessageWindow m_msgWindow = null;
protected WaveFile m_file = null;
public wave_in()
{
//m_msgWindow = new SoundMessageWindow(this);
m_file = new WaveFile();
}
public uint NumDevices()
{
return (uint)waveInGetNumDevs();
}
public wave.MMSYSERR GetDeviceName(uint deviceId, ref string prodName)
{
WAVEINCAPS caps = new WAVEINCAPS();
wave.MMSYSERR result = waveInGetDevCaps(deviceId, caps, caps.Size);
if (result != wave.MMSYSERR.noerror)
return result;
prodName = caps.szPname;
return wave.MMSYSERR.noerror;
}
public void BlockDone()
{
m_file.BlockDone();
}
public wave.MMSYSERR Preload(int maxRecordLength_ms, int bufferSize)
{
if (m_file != null)
return m_file.Preload(0, m_msgWindow.Hwnd, maxRecordLength_ms, bufferSize);
return wave.MMSYSERR.noerror;
}
public void Stop()
{
if (m_file != null)
m_file.Stop();
}
public wave.MMSYSERR Start()
{
if (m_file != null)
return m_file.Start();
return wave.MMSYSERR.noerror;
}
public bool Done()
{
return m_file.Done;
}
public wave.MMSYSERR Save(string fileName)
{
if (m_file != null)
return m_file.Save(fileName);
return wave.MMSYSERR.noerror;
}
public void Dispose()
{
m_msgWindow.Dispose();
if (m_file != null)
m_file.Dispose();
}
[DllImport("coredll.dll")]
protected static extern int waveInGetNumDevs();
[DllImport("coredll.dll")]
private static extern wave.MMSYSERR waveInOpen(ref IntPtr phwi, uint uDeviceID, wave.WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwInstance, uint fdwOpen);
[DllImport("coredll.dll")]
private static extern wave.MMSYSERR waveInPrepareHeader(IntPtr hwi, wave.WAVEHDR pwh, uint cbwh);
[DllImport("coredll.dll")]
private static extern wave.MMSYSERR waveInUnprepareHeader(IntPtr hwi, wave.WAVEHDR pwh, uint cbwh);
[DllImport("coredll.dll")]
protected static extern wave.MMSYSERR waveInClose(IntPtr hwi);
[DllImport("coredll.dll")]
protected static extern wave.MMSYSERR waveInReset(IntPtr hwi);
[DllImport("coredll.dll")]
protected static extern wave.MMSYSERR waveInStart(IntPtr hwi);
[DllImport("coredll.dll")]
protected static extern wave.MMSYSERR waveInStop(IntPtr hwi);
[DllImport("coredll.dll")]
private static extern wave.MMSYSERR waveInAddBuffer(IntPtr hwi, wave.WAVEHDR pwh, uint cbwh);
protected class WAVEINCAPS
{
const uint WAVEINCAPS_SIZE = 80;
private byte[] m_data = null;
public uint Size { get { return (uint)WAVEINCAPS_SIZE; } }
public ushort wMid { get { return BitConverter.ToUInt16(m_data, 0); } }
public ushort wPid { get { return BitConverter.ToUInt16(m_data, 2); } }
public uint vDriverVersion { get { return BitConverter.ToUInt32(m_data, 4); } }
public uint dwFormats { get { return BitConverter.ToUInt32(m_data, 72); } }
public ushort wChannels { get { return BitConverter.ToUInt16(m_data, 76); } }
public ushort wReserved1 { get { return BitConverter.ToUInt16(m_data, 78); } }
public string szPname
{
get
{
char[] bytes = new char[32];
for (int i = 0; i < 32; i++)
{
bytes[i] = (char)BitConverter.ToUInt16(m_data, i * 2 + 8);
}
return new string(bytes);
}
}
public WAVEINCAPS()
{
m_data = new byte[WAVEINCAPS_SIZE];
}
public static implicit operator byte[](WAVEINCAPS caps)
{
return caps.m_data;
}
}
[DllImport("coredll.dll")]
protected static extern wave.MMSYSERR waveInGetDevCaps(uint uDeviceID, byte[] pwic, uint cbwic);
public static void TestProc(MainTest.DisplayLineDelegate showLine)
{
wave_in wi = null;
try
{
wi = new wave_in();
uint numDevices = wi.NumDevices();
if (numDevices < 1)
{
showLine("FAILURE: No valid sound drivers detected");
return;
}
showLine(string.Format("{0} device{1} detected:", numDevices, numDevices != 1 ? "s" : ""));
for (uint i = 0; i < numDevices; i++)
{
string prodName = "";
if (wave.MMSYSERR.noerror != wi.GetDeviceName(i, ref prodName))
{
showLine(string.Format(" {0}: Failed to get name", i));
}
else
{
showLine(string.Format(" {0}: {1}", i, prodName));
}
}
showLine("Setting max time to 3 seconds");
showLine("Using 256KB buffers");
if (wave.MMSYSERR.noerror != wi.Preload(3000, 256 * 1024))
{
showLine("FAILURE: Failed to preload buffers");
}
showLine("Starting recording...");
if (wave.MMSYSERR.noerror != wi.Start())
{
showLine("FAILURE: Failed to start recording");
}
showLine("Waiting for 2 seconds...");
Thread.Sleep(2000);
showLine("Stopping recording early");
wi.Stop();
String fileName = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
fileName = Path.GetDirectoryName(fileName);
fileName = Path.Combine(fileName, "test.wav");
showLine("Saving file test.wav");
if (wave.MMSYSERR.noerror != wi.Save(fileName))
{
showLine("FAILURE: Failed to save file");
}
}
finally
{
if (wi != null)
wi.Dispose();
}
}
}
}