📄 main.frm
字号:
' Open the audio input device - I removed the reference to sink as a callback
' that was in the original call
' WAVE_MAPPER means to open any device that can handle the type of audio
' (specified in WF) that we want, preferably the one set as your default.
rc = waveInOpen(pDevHandle, WAVE_MAPPER, WF, 0, 0, CALLBACK_NULL)
If (rc <> 0) Then ' Now make sure that there are no errors
waveInGetErrorText rc, msg, Len(msg)
MsgBox msg
Exit Sub
End If
' pDevHandle now contains a pointer to reference further device calls
' (In other words, waveInOpen found a device for us to use, then gave
' us a pointer so we can keep using the device)
' Now we check to make sure it got a device
If (pDevHandle = 0) And (rc = 0) Then
MsgBox "Couldn't start capturing audio!", vbExclamation
Exit Sub
End If
' We have memory, we have an open wave device, now we assign it the buffer
' First, get the header ready - define it
With pWaveHeader
' .lpData = pWaveMem 'Points to where to save data
.lpData = pData 'Points to where to save data
.dwBufferLength = pcSamplesPerSecond * 2 * Buffer.Text 'Size of buffer in bytes
.dwBytesRecorded = 0 'How much data is recorded so far
.dwUser = 0 ' I don't know what goes here
.dwFlags = 0
.dwLoops = 0 ' Not used for input buffers
End With
' Now we need to prepare the header with the function (the header is 32 bytes big)
rc = waveInPrepareHeader(pDevHandle, pWaveHeader, Len(pWaveHeader))
' And assign the buffer to be filled
rc = waveInAddBuffer(pDevHandle, pWaveHeader, Len(pWaveHeader))
' And now start filling the buffer
rc = waveInStart(pDevHandle)
'Set how often to update the graph
Timer1.Interval = 50
RateTimer.Interval = 3000
' Everything seems to have executed correctly, so change the caption
Command1.Caption = "Stop Recording"
End Sub
Public Function getaddr(ByVal bla As Long) As Long
getaddr = bla
End Function
Private Sub Stop_Recording()
' Close the waveout device
rc = waveInReset(pDevHandle)
rc = waveInClose(pDevHandle)
'I don't need to deallocate the memory because now I use the array
' De-allocate any memory used
' rc = HeapDestroy(pWaveHeap)
' pWaveHeap = 0
Timer1.Interval = 0
End Sub
Private Sub Form_Unload(Cancel As Integer)
'Do these commands before exiting the program
' Make absolutely sure that I closed the device
rc = waveInReset(pDevHandle)
rc = waveInClose(pDevHandle)
' De-allocate any memory used (just for good housekeeping)
'rc = HeapDestroy(pWaveHeap)
End Sub
Private Sub RateTimer_Timer()
' A pulse did not come in the expected range - reset the output to 0
HeartRate.Text = 0
Comment.Text = "You appear to be dead. Perhaps you should call 911"
End Sub
Private Sub Timer1_Timer()
Update_Graph
End Sub
Function findY(ByVal index As Integer) As Long
'Calculate the y-value (equals average of data through the point)
Dim i As Long
Dim startx As Long
Dim endx As Long
Static prevYneg As Boolean
startx = Int(index / Picture1.ScaleWidth * pWaveHeader.dwBufferLength / 2)
endx = Int((index + 1) / Picture1.ScaleWidth * pWaveHeader.dwBufferLength / 2)
If endx > pcSamplesPerSecond * pcMaxSeconds Then endx = pcSamplesPerSecond * pcMaxSeconds
findY = 0
If (startx = endx) Then
findY = data(startx)
Else
'findY = data(startx)
For i = startx To endx
findY = findY + data(i)
Next i
findY = findY / (startx - endx)
End If
findY = findY / 2 ^ 16 * Picture1.ScaleHeight
If (prevYneg) Then
If (findY > TriggerLevel.Text * Picture1.ScaleHeight / 2) Then
edge_trigger (index)
prevYneg = False
End If
ElseIf (findY < TriggerLevel.Text * Picture1.ScaleHeight / 2) Then
prevYneg = True
End If
If (maxY < findY) Then maxY = findY
End Function
Function findTrigger()
'Determine what level to set the trigger point to
' - evaluated by .5*peak output
If (maxY > 5) Then
TriggerLevel.Text = maxY / Picture1.ScaleHeight
Else
TriggerLevel.Text = 0.5
End If
maxY = 0
End Function
Function edge_trigger(ByVal index As Integer)
'An edge trigger has occured, calculate the heart rate
Static prevIndex As Integer
If (index <> prevIndex) Then
If (index > prevIndex) Then
HeartRate.Text = Int(60 / Buffer * Picture1.ScaleWidth / (index - prevIndex) * 10) / 10
Else
HeartRate.Text = Int(60 / Buffer * Picture1.ScaleWidth / (index - prevIndex + Picture1.ScaleWidth) * 10) / 10
End If
End If
'If HeartRate.Text < 40 Then
' HeartRate.Text = 10
'End If
prevIndex = index
'Put some comments in the heart rate
If HeartRate.Text > 300 Then
Comment.Text = "Heart rate is high. Electrodes connected correctly?"
ElseIf HeartRate.Text > 110 Then
Comment.Text = "Work that body!"
Beep
ElseIf HeartRate.Text > 50 Then
Comment.Text = "Dum de dum de do"
Beep
Else
Comment.Text = "Yawn"
Beep
End If
' Assume a minimum heart rate of 20BPM and estimate when the worst case pulse should come
RateTimer.Enabled = False
RateTimer.Interval = 3000
RateTimer.Enabled = True
End Function
Private Sub Update_Graph()
'The timer has precidence over other processes, so when it goes
' off, the wave device stops writing to the data(). This means
' that if we read the data() now, it may be mixed with old data
' To solve this problem, I increased the delay to write the output
' In other words, say we just read in 1000 bytes making a total of 5000
' bytes read so far. We won't update the bytes 4000 to 5000 on the
' plot, but will update bytes 3000 to 2000 (the previous chunk of data
' read in)
Dim Point As Long 'The point to read the value
Dim refreshLeft As Long 'The left point to refresh
Dim refreshRight As Long 'The right point to refresh
Dim numPoints As Long 'The number of points to graph
Dim i As Long 'Some random variable
Dim Yval(pcSamplesPerSecond * 2 * pcMaxSeconds + 1) As Long 'The Y-values
Dim futureX As Integer 'What the X-coordinate is to refresh the data next time
Dim mmdata As MMTIME ' Used to find how much data we've read
Static prevX As Long ' The last X coordinate updated
Static nowX As Long ' The one before the last X coord updated - update prevX to nowX on plot
' First find out how much we've recorded
mmdata.wType = TIME_BYTES
rc = waveInGetPosition(pDevHandle, mmdata, Len(mmdata))
'Text1.Text now has the byte to read from in data()
Text1.Text = mmdata.dwData Mod pWaveHeader.dwBufferLength
' Then find out what the x-coord is for where we are
futureX = Int(Text1.Text / (pWaveHeader.dwBufferLength) * Picture1.ScaleWidth)
' Calculate the data points and refresh the data for the previous data set
If (prevX > nowX) Then 'We've wrapped around the screen
For i = prevX To Picture1.ScaleWidth
Yval(i) = findY(i)
Next i
For i = 0 To nowX
Yval(i) = findY(i)
Next i
Else
For i = prevX To nowX
Yval(i) = findY(i)
Next i
End If
'Erase the parts that need to be refreshed and draw the new stuff (but the last
' data point may be bad, so don't draw that one)
If (prevX > nowX) Then
Picture1.Line (0, -Picture1.ScaleTop)-(nowX, Picture1.ScaleTop), Picture1.BackColor, B
Picture1.Line (prevX + 1, -Picture1.ScaleTop)-(Picture1.ScaleWidth, Picture1.ScaleTop), Picture1.BackColor, B
For i = 1 To nowX
Picture1.Line ((i - 1), -Yval(i - 1))-((i), -Yval(i))
Next i
For i = prevX + 1 To Picture1.ScaleWidth
Picture1.Line ((i - 1), -Yval(i - 1))-((i), -Yval(i))
Next i
Else
Picture1.Line (prevX + 1, -Picture1.ScaleTop)-(nowX, Picture1.ScaleTop), Picture1.BackColor, B
For i = prevX + 1 To nowX
Picture1.Line ((i - 1), -Yval(i - 1))-((i), -Yval(i))
'Picture1.Circle (i, Yval(i)), 1
Next i
End If
'Now update the pointers so we can keep everything straight
prevX = nowX
'If prevX < 0 Then prevX = 0
nowX = futureX
'If we've reached the end of the buffer, reset it (but we like the old data, so keep it there)
If (pWaveHeader.dwFlags = WHDR_DONE) And (Command1.Caption = "Stop Recording") Then
rc = waveInAddBuffer(pDevHandle, pWaveHeader, Len(pWaveHeader))
' pWaveHeader.dwBytesRecorded = 0
'Also, do some cleanup that needs to be done
If (AutoTrigger.Value = 1) Then
rc = findTrigger()
End If
Picture1.Line (0, -TriggerLevel.Text * Picture1.ScaleHeight / 2)-(Picture1.ScaleWidth, -TriggerLevel.Text * Picture1.ScaleHeight / 2), &HFFFFC0
End If
'Picture1.Line (0, 0)-(Picture1.ScaleWidth, Picture1.ScaleHeight)
End Sub
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -