Hello,
I need help.. I have problem with splitting left & right channel from captured stream from mic (or sound card) Below code corectly record sound from mic and saving into the wav file pairs left channel, right channel, left... How recognize (split) in CapturedData left and right channel ?? [method CreateCaptureBuffer()]
For InPos = 1 To 24000 - 1 Step 2 buffLeft(OutPos) = CaptureData(InPos) OutPos += 1 Next InPos
I'm tired of unsuccessful attempts...
Regards, Schift
Imports Microsoft.DirectX
Imports Microsoft.DirectX.DirectSound
Imports System.Threading
Imports System.IO
Public Class Form1
Public PositionNotify As BufferPositionNotify() = New Microsoft.DirectX.DirectSound.BufferPositionNotify(NumberRecordNotifications) {}
Public Const NumberRecordNotifications As Integer = 16
Public NotificationEvent As AutoResetEvent = Nothing
Public applicationBuffer As CaptureBuffer = Nothing
Public CaptureDeviceGuid As Guid = Guid.Empty
Public applicationDevice As Capture = Nothing
Private FileName As String = String.Empty
Private FileName2 As String = String.Empty
Public applicationNotify As Notify = Nothing
Private NotifyThread As Thread = Nothing
Private Wave As FileStream = Nothing
Private Writer As BinaryWriter = Nothing
Private Path As String = String.Empty
Public CaptureBufferSize As Integer = 0
Public NextCaptureOffset As Integer = 0
Private Recording As Boolean = False
Public InputFormat As WaveFormat
Private SampleCount As Integer = 0
Public NotifySize As Integer = 0
Private counter As Integer = 0
Private Capturing As Boolean = False
Private strx As New MemoryStream
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim captureDevicesCollection As New CaptureDevicesCollection
Console.WriteLine(captureDevicesCollection(2).Description)
CaptureDeviceGuid = captureDevicesCollection(2).DriverGuid
With InputFormat
.AverageBytesPerSecond = 192000
.BitsPerSample = 16
.BlockAlign = 4
.Channels = 2
.FormatTag = WaveFormatTag.Pcm
.SamplesPerSecond = 48000
End With
FileName = "C:\test.wav"
' FileName2 = "C:\testLeft.wav"
Try
applicationDevice = New Capture(CaptureDeviceGuid)
CreateCaptureBuffer()
OnCreateSoundFile()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
Private Sub CreateCaptureBuffer()
'-----------------------------------------------------------------------------
' Name: CreateCaptureBuffer()
' Desc: Creates a capture buffer and sets the format
'-----------------------------------------------------------------------------
Dim dscheckboxd As New CaptureBufferDescription()
If applicationNotify IsNot Nothing Then
applicationNotify.Dispose()
applicationNotify = Nothing
End If
If applicationBuffer IsNot Nothing Then
applicationBuffer.Dispose()
applicationBuffer = Nothing
End If
If 0 = InputFormat.Channels Then
Return
End If
' Set the notification size
NotifySize = IIf((1024 > InputFormat.AverageBytesPerSecond / 8), 1024, (InputFormat.AverageBytesPerSecond / 8))
NotifySize -= NotifySize Mod InputFormat.BlockAlign
' Set the buffer sizes
CaptureBufferSize = NotifySize * NumberRecordNotifications
' Create the capture buffer
dscheckboxd.BufferBytes = CaptureBufferSize
InputFormat.FormatTag = WaveFormatTag.Pcm
dscheckboxd.Format = InputFormat
' Set the format during creatation
applicationBuffer = New CaptureBuffer(dscheckboxd, applicationDevice)
NextCaptureOffset = 0
InitNotifications()
End Sub
Private Sub InitNotifications()
'-----------------------------------------------------------------------------
' Name: InitNotifications()
' Desc: Inits the notifications on the capture buffer which are handled
' in the notify thread.
'-----------------------------------------------------------------------------
If applicationBuffer Is Nothing Then
Throw New NullReferenceException()
End If
' Create a thread to monitor the notify events
If NotifyThread Is Nothing Then
NotifyThread = New Thread(New ThreadStart(AddressOf WaitThread))
Capturing = True
NotifyThread.Start()
' Create a notification event, for when the sound stops playing
NotificationEvent = New AutoResetEvent(False)
End If
' Setup the notification positions
For i As Integer = 0 To NumberRecordNotifications - 1
PositionNotify(i).Offset = (NotifySize * i) + NotifySize - 1
PositionNotify(i).EventNotifyHandle = NotificationEvent.Handle
Next
applicationNotify = New Notify(applicationBuffer)
' Tell DirectSound when to notify the app. The notification will come in the from
' of signaled events that are handled in the notify thread.
applicationNotify.SetNotificationPositions(PositionNotify, NumberRecordNotifications)
End Sub
Private Sub WaitThread()
While Capturing
'Sit here and wait for a message to arrive
NotificationEvent.WaitOne(Timeout.Infinite, True)
RecordCapturedData()
End While
End Sub
Private Sub RecordCapturedData()
'-----------------------------------------------------------------------------
' Name: RecordCapturedData()
' Desc: Copies data from the capture buffer to the output buffer
'-----------------------------------------------------------------------------
Dim CaptureData As Byte() = Nothing
Dim buffLeft As Byte() = Nothing
Dim buffRight As Byte() = Nothing
Dim ReadPos As Integer
Dim CapturePos As Integer
Dim LockSize As Integer
applicationBuffer.GetCurrentPosition(CapturePos, ReadPos)
LockSize = ReadPos - NextCaptureOffset
If LockSize < 0 Then
LockSize += CaptureBufferSize
End If
' Block align lock size so that we are always write on a boundary
LockSize -= (LockSize Mod NotifySize)
If 0 = LockSize Then
Return
End If
' Read the capture buffer.
CaptureData = DirectCast(applicationBuffer.Read(NextCaptureOffset, GetType(Byte), LockFlag.None, LockSize), Byte())
ReDim buffLeft(24000)
' ReDim buffLeft(UBound(CaptureData))
''ReDim buffRight(UBound(buffLeft))
Dim InPos As Long = 0
Dim OutPos As Long = 0
Dim counter As Long = 0
For InPos = 1 To 24000 - 1 Step 2
buffLeft(OutPos) = CaptureData(InPos)
OutPos += 1
Next InPos
SampleCount += buffLeft.Length - 1
Writer.Write(buffLeft, 0, buffLeft.Length - 1)
' Move the capture offset along
NextCaptureOffset += CaptureData.Length
NextCaptureOffset = NextCaptureOffset Mod CaptureBufferSize
' Circular buffer
End Sub
Private Sub checkboxRecord_CheckedChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles checkboxRecord.CheckedChanged
Recording = Not Recording
StartOrStopRecord(Recording)
If Not Recording Then
checkboxRecord.Enabled = False
End If
End Sub
Private Sub StartOrStopRecord(ByVal StartRecording As Boolean)
'-----------------------------------------------------------------------------
' Name: StartOrStopRecord()
' Desc: Starts or stops the capture buffer from recording
'-----------------------------------------------------------------------------
If StartRecording Then
' Create a capture buffer, and tell the capture
' buffer to start recording
CreateCaptureBuffer()
applicationBuffer.Start(True)
Else
' Stop the buffer, and read any data that was not
' caught by a notification
applicationBuffer.[Stop]()
RecordCapturedData()
Writer.Seek(4, SeekOrigin.Begin)
' Seek to the length descriptor of the RIFF file.
Writer.Write(CInt(SampleCount + 36))
' Write the file length, minus first 8 bytes of RIFF description.
Writer.Seek(40, SeekOrigin.Begin)
' Seek to the data length descriptor of the RIFF file.
Writer.Write(SampleCount)
' Write the length of the sample data in bytes.
Writer.Close()
' Close the file now.
Writer = Nothing
'<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
'-------------------------------------
' Set the writer to null.
' Set the FileStream to null.
Wave = Nothing
End If
End Sub
Private Sub CreateRIFF()
'*************************************************************************
'
' Here is where the file will be created. A
' wave file is a RIFF file, which has chunks
' of data that describe what the file contains.
' A wave RIFF file is put together like this:
'
' The 12 byte RIFF chunk is constructed like this:
' Bytes 0 - 3 : 'R' 'I' 'F' 'F'
' Bytes 4 - 7 : Length of file, minus the first 8 bytes of the RIFF description.
' (4 bytes for "WAVE" + 24 bytes for format chunk length +
' 8 bytes for data chunk description + actual sample data size.)
' Bytes 8 - 11: 'W' 'A' 'V' 'E'
'
' The 24 byte FORMAT chunk is constructed like this:
' Bytes 0 - 3 : 'f' 'm' 't' ' '
' Bytes 4 - 7 : The format chunk length. This is always 16.
' Bytes 8 - 9 : File padding. Always 1.
' Bytes 10- 11: Number of channels. Either 1 for mono, or 2 for stereo.
' Bytes 12- 15: Sample rate.
' Bytes 16- 19: Number of bytes per second.
' Bytes 20- 21: Bytes per sample. 1 for 8 bit mono, 2 for 8 bit stereo or
' 16 bit mono, 4 for 16 bit stereo.
' Bytes 22- 23: Number of bits per sample.
'
' The DATA chunk is constructed like this:
' Bytes 0 - 3 : 'd' 'a' 't' 'a'
' Bytes 4 - 7 : Length of data, in bytes.
' Bytes 8 -...: Actual sample data.
'
' **************************************************************************
' Open up the wave file for writing.
Wave = New FileStream(FileName, FileMode.Create)
' WaveFileLeft = New FileStream(FileName2, FileMode.Create)
Writer = New BinaryWriter(Wave)
' Set up file with RIFF chunk info.
Dim ChunkRiff As Char() = {"R"c, "I"c, "F"c, "F"c}
Dim ChunkType As Char() = {"W"c, "A"c, "V"c, "E"c}
Dim ChunkFmt As Char() = {"f"c, "m"c, "t"c, " "c}
Dim ChunkData As Char() = {"d"c, "a"c, "t"c, "a"c}
Dim shPad As Short = 1
' File padding
Dim nFormatChunkLength As Integer = &H10
' Format chunk length.
Dim nLength As Integer = 0
' File length, minus first 8 bytes of RIFF description. This will be filled in later.
Dim shBytesPerSample As Short = 0
' Bytes per sample.
' Figure out how many bytes there will be per sample.
If 8 = InputFormat.BitsPerSample AndAlso 1 = InputFormat.Channels Then
shBytesPerSample = 1
ElseIf (8 = InputFormat.BitsPerSample AndAlso 2 = InputFormat.Channels) OrElse (16 = InputFormat.BitsPerSample AndAlso 1 = InputFormat.Channels) Then
shBytesPerSample = 2
ElseIf 16 = InputFormat.BitsPerSample AndAlso 2 = InputFormat.Channels Then
shBytesPerSample = 4
End If
' Fill in the riff info for the wave file.
Writer.Write(ChunkRiff)
Writer.Write(nLength)
Writer.Write(ChunkType)
'.AverageBytesPerSecond = 192000
'.BitsPerSample = 16
'.BlockAlign = 4
'.Channels = 2
'.FormatTag = WaveFormatTag.Pcm
'.SamplesPerSecond = 48000
' Fill in the format info for the wave file.
Writer.Write(ChunkFmt)
Writer.Write(nFormatChunkLength)
Writer.Write(shPad)
Writer.Write(InputFormat.Channels) 'channels
Writer.Write(InputFormat.SamplesPerSecond) 'samplepersecond
Writer.Write(InputFormat.AverageBytesPerSecond) 'averagebytespersecond
Writer.Write(shBytesPerSample) 'bytespersample
Writer.Write(InputFormat.BitsPerSample) 'bitspersample
' Now fill in the data chunk.
Writer.Write(ChunkData)
Writer.Write(CInt(0))
' The sample length will be written in later.
'<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
End Sub
Private Sub OnCreateSoundFile()
'-----------------------------------------------------------------------------
' Name: OnCreateSoundFile()
' Desc: Called when the user requests to save to a sound file
'-----------------------------------------------------------------------------
If Recording Then
' Stop the capture and read any data that
' was not caught by a notification
StartOrStopRecord(False)
Recording = False
End If
' Update the UI controls to show the sound as loading a file
checkboxRecord.Enabled = False
Try
CreateRIFF()
Catch
End Try
' Update the UI controls to show the sound as the file is loaded
labelFilename.Text = FileName
checkboxRecord.Enabled = True
' Remember the path for next time
Path = FileName.Substring(0, FileName.LastIndexOf("\"))
End Sub
End Class