Link to home
Start Free TrialLog in
Avatar of rbichon
rbichon

asked on

Record WAV with MCI and specific device

How can I record a wav file from a specific device using MCI API (mciSendString I think) when the device is not set up as the default recording device? I want to programmatically choose the device.
Avatar of The_Biochemist
The_Biochemist

MCI isn't really used in the .net world all that much... why not try having a search for the windows media encoder SDK on MSDN (msdn.microsoft.com) it has much more flexinbility and uses managed code.
Some references for you...

MSDN:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmencode/htm/windowsmediaencoderautomation.asp

Examples:
General information
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmencode/htm/creatinganencoderapplication.asp

Using a device as the source e.g. microphone / windows mixer output:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmencode/htm/usingadeviceasasource.asp

Happy Coding!

P.S. If you use the encoder you can also get a licence to use one of those little 'designed for media player' icons which is quite cool if you are going to be marketing the software!
Avatar of rbichon

ASKER

I have no idea what I am looking at. What libraries do I reference? I love how Microsoft doesn't even have VB.Net examples on their own website. I am getting a lot or undefined types like IWMEncDeviceControlPlugin in my code. I am somewhat of a beginner. Plus their examples are a bit overkill and not very well commented. Can you past in an example here that will select a device for recording and record a wma on it? Also, I don't understand the SrcAud.SetInput("Device://Device resource name") part. How am I supposed to know the Device Resource Name? What if I need to set it programmatically?
Avatar of Howard Cantrell
Here is a sample of some code that I was playing with on sound.....
You will need to download micro$oft direct x

'FORM 1

Public Class Form1
    Inherits System.Windows.Forms.Form
    Dim Sound As New clsPlaySound("C:\waves\TrainWhirsl.wav")   '<-----File Name
    Dim RecSoundBites As New clsRecordSound("c:\NewOpen.wav", "c:\NewSound.wav") '<-----File Name
    Dim iStart As Short
    Dim iEnd As Short
#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents GroupBox1 As System.Windows.Forms.GroupBox
    Friend WithEvents btnRecord As System.Windows.Forms.Button
    Friend WithEvents btnPause As System.Windows.Forms.Button
    Friend WithEvents btnResume As System.Windows.Forms.Button
    Friend WithEvents BtnStop As System.Windows.Forms.Button
    Friend WithEvents btnSave As System.Windows.Forms.Button
    Friend WithEvents BtnClose As System.Windows.Forms.Button
    Friend WithEvents BtnRecTime As System.Windows.Forms.Button
    Friend WithEvents Button3 As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.GroupBox1 = New System.Windows.Forms.GroupBox
        Me.BtnRecTime = New System.Windows.Forms.Button
        Me.BtnClose = New System.Windows.Forms.Button
        Me.btnSave = New System.Windows.Forms.Button
        Me.BtnStop = New System.Windows.Forms.Button
        Me.btnResume = New System.Windows.Forms.Button
        Me.btnPause = New System.Windows.Forms.Button
        Me.btnRecord = New System.Windows.Forms.Button
        Me.Button3 = New System.Windows.Forms.Button
        Me.GroupBox1.SuspendLayout()
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(16, 16)
        Me.Button1.Name = "Button1"
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Play"
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(120, 16)
        Me.Button2.Name = "Button2"
        Me.Button2.TabIndex = 1
        Me.Button2.Text = "Stop"
        '
        'GroupBox1
        '
        Me.GroupBox1.Controls.Add(Me.Button3)
        Me.GroupBox1.Controls.Add(Me.BtnRecTime)
        Me.GroupBox1.Controls.Add(Me.BtnClose)
        Me.GroupBox1.Controls.Add(Me.btnSave)
        Me.GroupBox1.Controls.Add(Me.BtnStop)
        Me.GroupBox1.Controls.Add(Me.btnResume)
        Me.GroupBox1.Controls.Add(Me.btnPause)
        Me.GroupBox1.Controls.Add(Me.btnRecord)
        Me.GroupBox1.Location = New System.Drawing.Point(12, 112)
        Me.GroupBox1.Name = "GroupBox1"
        Me.GroupBox1.Size = New System.Drawing.Size(260, 148)
        Me.GroupBox1.TabIndex = 2
        Me.GroupBox1.TabStop = False
        Me.GroupBox1.Text = "Record Sound"
        '
        'BtnRecTime
        '
        Me.BtnRecTime.Location = New System.Drawing.Point(32, 68)
        Me.BtnRecTime.Name = "BtnRecTime"
        Me.BtnRecTime.Size = New System.Drawing.Size(80, 24)
        Me.BtnRecTime.TabIndex = 5
        Me.BtnRecTime.Text = "Record Time"
        '
        'BtnClose
        '
        Me.BtnClose.Location = New System.Drawing.Point(168, 68)
        Me.BtnClose.Name = "BtnClose"
        Me.BtnClose.Size = New System.Drawing.Size(56, 24)
        Me.BtnClose.TabIndex = 7
        Me.BtnClose.Text = "Close"
        '
        'btnSave
        '
        Me.btnSave.Location = New System.Drawing.Point(112, 68)
        Me.btnSave.Name = "btnSave"
        Me.btnSave.Size = New System.Drawing.Size(56, 24)
        Me.btnSave.TabIndex = 6
        Me.btnSave.Text = "Save"
        '
        'BtnStop
        '
        Me.BtnStop.Location = New System.Drawing.Point(180, 24)
        Me.BtnStop.Name = "BtnStop"
        Me.BtnStop.Size = New System.Drawing.Size(56, 24)
        Me.BtnStop.TabIndex = 4
        Me.BtnStop.Text = "Stop"
        '
        'btnResume
        '
        Me.btnResume.Location = New System.Drawing.Point(124, 24)
        Me.btnResume.Name = "btnResume"
        Me.btnResume.Size = New System.Drawing.Size(56, 24)
        Me.btnResume.TabIndex = 3
        Me.btnResume.Text = "Resume"
        '
        'btnPause
        '
        Me.btnPause.Location = New System.Drawing.Point(68, 24)
        Me.btnPause.Name = "btnPause"
        Me.btnPause.Size = New System.Drawing.Size(56, 24)
        Me.btnPause.TabIndex = 2
        Me.btnPause.Text = "Pause"
        '
        'btnRecord
        '
        Me.btnRecord.Location = New System.Drawing.Point(12, 24)
        Me.btnRecord.Name = "btnRecord"
        Me.btnRecord.Size = New System.Drawing.Size(56, 24)
        Me.btnRecord.TabIndex = 1
        Me.btnRecord.Text = "Record"
        '
        'Button3
        '
        Me.Button3.Location = New System.Drawing.Point(16, 104)
        Me.Button3.Name = "Button3"
        Me.Button3.Size = New System.Drawing.Size(112, 24)
        Me.Button3.TabIndex = 8
        Me.Button3.Text = "Delete a Section"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Controls.Add(Me.GroupBox1)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.GroupBox1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Sound.PlaySound()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Sound.StopSound()
    End Sub

    Private Sub btnRecord_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRecord.Click, btnPause.Click, _
    BtnRecTime.Click, btnResume.Click, btnSave.Click, BtnStop.Click, BtnClose.Click

        Select Case sender.tabindex
            Case 1   ' start recording
                RecSoundBites.sCmd = "Record " & RecSoundBites.FileName
                RecSoundBites.OpenFile()
                Exit Sub
            Case 2   ' pause recording
                RecSoundBites.sCmd = "Pause " & RecSoundBites.FileName
            Case 3   ' resume recording
                RecSoundBites.sCmd = "Resume " & RecSoundBites.FileName
            Case 4   ' stop recording
                RecSoundBites.sCmd = "Stop " & RecSoundBites.FileName
            Case 5 ' and you can record for a number of milliseconds and then terminate:
                ' record for only 2 seconds
                RecSoundBites.sCmd = "Record " & RecSoundBites.FileName & " to 2000 wait"
            Case 6  ' When you have completed your recording, you must save the WAV file to file
                RecSoundBites.sCmd = "Save " & RecSoundBites.FileName & " " & RecSoundBites.SaveFileName
            Case 7  ' close the device with Close command:
                RecSoundBites.sCmd = "Close " & RecSoundBites.FileName
                'Case 5   ' You can also set the time format in milliseconds:
                '    RecSoundBites.sCmd = "Set " & RecSoundBites.FileName & " time format milliseconds"
            Case 8  ' Delete a section ("delete capture from 1 to 200",
                RecSoundBites.sCmd = "Delete " & RecSoundBites.FileName & " from " & istart & " to " & iend
        End Select
        RecSoundBites.RecFile()
    End Sub
End Class

'CLASS 1

Imports System
Imports DxVBLib

Public Class clsPlaySound

    ' Basic Wave and MIDI Player Class for VB.net 1.1
    ' Requires COM-Object : DirectX7
    'IN YOUR FORM
    '
    'Dim Sound As New clsPlaySound("C:\i386\town.mid") <---Sample
    'Sound.PlaySound()
    ' or
    'Sound.StopSound()
    '
    Private Declare Function mciSendString Lib "Winmm.dll" Alias "mciSendStringA" _
            (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
             ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer

    Private File As String
    Private m_dx As New DirectX7
    Private m_ds As DirectSound
    Private lRet As Integer
    Public Sub New(ByVal strFileName As String)
        Me.File = strFileName
    End Sub
    ' To show what file is selected (if needed)
    Public ReadOnly Property FileName() As String
        Get
            Return File
        End Get
    End Property
    Public Function PlaySound() As Boolean
        If InitAudio() = True Then
            If PlayFile() = True Then
                Return True
            Else
                Return False
            End If
        Else
            ' Audiohardware not found
            ' exit here
            Return False
        End If
    End Function
    Private Function InitAudio() As Boolean
        m_ds = m_dx.DirectSoundCreate("")

        If Err.Number <> 0 Then
            Return False
        Else
            Return True
        End If
    End Function
    Private Function PlayFile() As Boolean
        Try
            StopFile()
            lRet = mciSendString("open " & Me.File & " alias track", "", 0, 0)
            lRet = mciSendString("play track", "", 0, 0)
            PlayFile = (lRet = 0)
        Catch ex As Exception
            Return False
        End Try
        Return True
    End Function
    Public Function CloseAudio()
        mciSendString("close all", 0, 0, 0)
    End Function
    Public Function StopSound() As Boolean
        StopFile()
    End Function
    Private Function StopFile() As Boolean
        Try
            lRet = mciSendString("stop track", "", 0, 0)
            lRet = mciSendString("close track", "", 0, 0)
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function

End Class

'CLASS 2

Public Class clsRecordSound
    Private Declare Function mciSendString Lib "Winmm.dll" Alias "mciSendStringA" _
        (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
         ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer

    Private File As String
    Private saveFile As String
    Private lRet As Integer
    Public sCmd As String
    Public Sub New(ByVal strFileName As String, ByVal strSaveFileName As String)
        Me.File = strFileName
        Me.saveFile = strSaveFileName
    End Sub
    ' To show what file is selected (if needed)
    Public ReadOnly Property SaveFileName() As String
        Get
            Return saveFile
        End Get
    End Property
    ' To show what file is selected (if needed)
    Public ReadOnly Property FileName() As String
        Get
            Return File
        End Get
    End Property
    Public Function OpenFile() As Boolean
        Try
            lRet = mciSendString("open new type waveaudio alias " & Me.File, 0&, 0, 0)
            'Bit size 8 or 16
            lRet = mciSendString("set " & Me.File & " capture bitspersample 8", 0&, 0, 0)
            '        Samples per Second...
            'The Samples per Second can be set using the samplespersec command.

            'Samples per sec that are supported:
            '11025   low(quality)
            '22050   medium(quality)
            '44100   high quality (CD music quality)
            lRet = mciSendString("set " & Me.File & " samplespersec 11025", 0&, 0, 0)

            ' Mono... Stereo...
            'Set the wav to record with one channel (1 = mono) or two channels (2 = stereo)
            lRet = mciSendString("set " & Me.File & " channels 1", 0&, 0, 0)

            lRet = mciSendString(sCmd, 0&, 0, 0)
            OpenFile = (lRet = 0)
        Catch ex As Exception
            Return False
        End Try
        Return True
    End Function
    Public Function RecFile() As Boolean
        Try
            lRet = mciSendString(sCmd, 0&, 0, 0)
            RecFile = (lRet = 0)
        Catch ex As Exception
            Return False
        End Try
        Return True
    End Function
    'You can delete any section
    Public Function DeleteSection(ByVal iStart As Int16, ByVal iEnd As Int16) As Boolean
        Try
            lRet = mciSendString("delete " & Me.File & " from " & iStart & " to " & iEnd, 0&, 0, 0)
            DeleteSection = (lRet = 0)
        Catch exp As Exception
            Return False
        End Try
        Return True
    End Function
End Class
Avatar of rbichon

ASKER

The code looks great and will be helpful. One probelm is that I don't see in your code where I can select a recording device. For example, I have a Dialogic Telephony card with four ports. Each of the ports are listed under the "Sound Recording" menu in Sounds and Audio Device Properties. They are listed as Dialogic Wave(dxxxB1C1), Dialogic Wave(dxxxB1C2), Dialogic Wave(dxxxB1C3), Dialogic Wave(dxxxB1C4). How can I programmatically select one of those ports for recording?
ASKER CERTIFIED SOLUTION
Avatar of Howard Cantrell
Howard Cantrell
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi rbichon,
Have you solved your question?