0
0

Here is a sub for recording and saving a WAV in any format in VB. fmod.bas should be in your VB project. This post includes all the info from my previous posts. It should work on any windows machine (95 to XP) without requiring any DLL except FMOD. I’ve run the exe as compiled from visual basic on a Win95 machine without the setup.exe….just the 40KB .exe and fmod.dll are required…This is much better than any other method to record WAVs in VB.

For a different approach, see
http://52.88.2.202/forum/viewtopic.php … t=writewav

My comments below in the sub should be clear, but for WAV header format explained differently, see
http://ccrma.stanford.edu/courses/422/p … aveFormat/
===== begin code =======
Sub RecordAndSaveWav(filepath As String, recordrate As Long, recordtime As Single, monostereo As Integer, bytespersample As Integer)
‘ usage notes:
‘ filepath examples: c:\path\file.wav, .\path\file.wav, or file.wav
‘ recordrate is in samples/sec (aka Hz)
‘ recordtime is in seconds and < 1 is OK.
‘ monostereo is 1 for mono, 2 for stereo
‘ bytespersample is 1 for 8 bit, 2 for 16 bit
‘ for copy and paste: RecordAndSaveWav(fpath,rrate,rtime,ms,bps)

Dim wavData() As Byte ‘ buffer to hold data
Dim ptr1 As Long, ptr2 As Long
Dim len1 As Long, len2 As Long
Dim samp As Long, result As Boolean
Dim recordsamples As Long, recordbytes As Long
Dim alloc_needs_this As Long

result = FSOUND_Init(recordrate, 32, 0)
If Not result Then MsgBox FSOUND_GetErrorString(“Init Error1: ” & FSOUND_GetError), vbOKOnly
recordsamples = Int(recordtime * recordrate) ‘ number of samples to record. recordbytes=recordsamples22 if 16 bit stereo
recordbytes = recordsamples * monostereo * bytespersample ‘ not used, but for demonstration
alloc_needs_this = &H8 * bytespersample Or &H20 * monostereo ‘ i’m glad this worked
samp = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, recordsamples, alloc_needs_this, recordrate, 255, 128, 255)
If samp = 0 Then MsgBox FSOUND_GetErrorString(FSOUND_GetError), vbOKOnly
result = FSOUND_Record_StartSample(samp, False)
If Not result Then MsgBox FSOUND_GetErrorString(“Record StartSample Error: ” & FSOUND_GetError), vbOKOnly
While FSOUND_Record_GetPosition() < recordsamples
Delay (0.1) ‘ delay a tenth of a second while recording. uses fewer resources than sleep?
Wend
result = FSOUND_Record_Stop()
If Not result Then MsgBox FSOUND_GetErrorString(“Record Stop Error: ” & FSOUND_GetError), vbOKOnly

‘ the following may have been needed in case less than recordsamples was actually recorded
recordbytes = Int(FSOUND_Sample_GetLength(samp) * monostereo * bytespersample)
‘########## the following is too remind me what never worked
‘ConvCStringToVBString raw_wav, ptr1 ‘ only can convert a few dozen characters … exits on chr(0)
‘##########
‘========= the following is to explain basic WAV pcm (non-compressed) format
‘ % indicates a hex value for a byte.
‘ In wav files, everything except the text fields are in little endian (reverse the bytes):
‘ 16000 => %3E%80 => %80%3E (16,000 in hex and in little endian)
‘ but sample rate is stored as 4 bytes, so 16,000 => %00%00%3E%80 => %80%3E%00%00
‘ dec2endian is for doing the conversion for exactly 4 bytes.

‘ below is how a WAV file header looks in Hex when opened with an editor with Hex:
‘ the parentheses below are for seperation clarity
‘==========================================
‘ RIFF
‘ (4 bytes specifying file size minus 8 bytes which is also 36 bytes plus wav data)
‘ WAVEfmt(%20)
‘ (%10%00%00%00)(%01%00)(%01 for mono, %02 for stereo)(%00)
‘ (4 bytes = sample rate … remember all bytes are reversed)
‘ (4 bytes = SampleRate * NumChannels * BitsPerSample/ 8)
‘ (1 byte = NumChannels * BitsPerSample/ 8 e.g. %02 represents 16 bit mono)(%00)
‘ (1 byte = BitsPerSample: 8 or 16, i.e. %08 or %10)(%00)
‘ data
‘ (4 bytes for file size minus 44, the actual size of the raw wav data which follows immediately)
‘ (actual wav data begins here)
‘==========================================
‘ if wav data is stereo, alternate the 1 byte [8-bit] or 2 byte [16-bit] samples like
‘ this: L,R,L,R,L,R,etc.
‘ 8-bit samples are stored as unsigned single bytes, ranging from 0 to 255, in hex that’s %00 to %FF
‘ 128 (%80) is zero or maybe +1.
‘ 16-bit [2 byte] samples are in a format called “2’s-complement signed”,
‘ ranging from -32768 to 32767. In hex, that’s 0000 up to 7FFF for positive and FFFF down to
‘ 8000 for negative. Oddly enough, 8000 is the lowest negative value.
‘ but they are stored in little endian so volume +23,661 => %5C%6D => %6D%5C
‘ negative example: -23,661 => 65535-23661=41874 => %A3%92 => (little endian) %92%A3

‘ Each chr$() returns a byte of ASCII text (a hex value in bits). It helps to have a
‘ calculator with base conversion and an ascii chart in hex and decimal. Note that chr(1)=%01,
‘ chr(2)=%02, chr(16)=%10, chr(15)=%FF, and chr(32)=%20=(space).

‘ Kill filepath ‘ delete old file!
wav_header$ = “RIFF” & dec2endian(recordbytes + 36) & “WAVEfmt” & Chr$(32) & _
Chr$(16) & Chr$(0) & Chr$(0) & Chr$(0) & Chr$(1) & Chr$(0) & Chr$(monostereo) & Chr$(0) & _
dec2endian(recordrate) & dec2endian(Int(recordrate * monostereo * bytespersample)) & _
Chr$(Int(monostereo * bytespersample)) & Chr$(0) & _
Chr$(Int(8 * bytespersample)) & Chr$(0) & “data” & dec2endian(recordbytes)
Open filepath For Binary As #1
Put #1, , wav_header$ ‘ without the $ it was printing 4 bytes at the beginnning

‘ by the following not using ptr2 or len2, it assumes the recording above did not go
‘ past the buffer specified by recordsample in FSOUND_sample_alloc above…and it shouldn’t
result = FSOUND_Sample_Lock(samp, 0, recordbytes, ptr1, ptr2, len1, len2)
If Not result Then MsgBox FSOUND_GetErrorString(“Sample Lock Error: ” & FSOUND_GetError), vbOKOnly
ReDim Preserve wavData(0 To len1 – 1) As Byte
Call CopyMemory(wavData(0), ByVal ptr1, len1)
‘ at this line you can modify pcmData WAV data before saving
Put #1, , wavData
result = FSOUND_Sample_Unlock(samp, ptr1, ptr2, len1, len2)
If Not result Then MsgBox FSOUND_GetErrorString(“Sample Unlock Error: ” & FSOUND_GetError), vbOKOnly
Close #1
FSOUND_Sample_Free (samp)
Erase wavData
FSOUND_Close
End Sub

‘======================

Sub Delay(y As Single)
‘ y seconds of delay, does not tie up resources
x = Timer
While Timer < x + y And halted <> “yes” And next_one <> “yes”
DoEvents
Wend
End Sub
‘=====================
Public Function dec2endian(ByVal dec_num As Long) As String
‘ converts a decimal number to 4 byte little endian ascii character string
Dim a, b, c, d As String
Dim aa, bb, cc, dd As Long
dd = Int(dec_num / 16777216)
cc = Int((dec_num – dd * 16777216) / 65536)
bb = Int((dec_num – dd * 16777216 – cc * 65536) / 256)
aa = dec_num – dd * 16777216 – cc * 65536 – bb * 256
a = Chr$(aa): b = Chr$(bb): c = Chr$(cc): d = Chr$(dd)
dec2endian = a & b & c & d
End Function
========= end code ==========

  • You must to post comments
0
0

I really don’t understand why you say it is a different approch, except for the endianess issus, the code do the same thing in the same way and is not “much better” than mine (and where it is better : cpu, memory, speed …).
It don’t say that to prove that my code is better than yours but some explanations on why your approch is different would be usefull (at least for me ๐Ÿ˜› )

  • You must to post comments
0
0

I didn’t intend to say it was better than your method, i was trying to say using FMOD for this is better than any other VB method that I know of for recording WAV files. The other methods use enormous DLLs that aren’t on other machines, require the newest Windows Media Player, or are kind of limited, finicky, or just unreliable. But i do like my way of forming the header better than yours ๐Ÿ˜›

I shoudl have placed at the top of the sub the following because if the file exists, it doesn’t crash or give an error message, it just writes over part of the existing file.

If Not Dir$(filepath) = “” Then
MsgBox “File already exists!”
Exit Sub
End If

Also all my error statements for FSOUND are wrong. For Example:
If Not result Then MsgBox FSOUND_GetErrorString(“Record StartSample Error: ” & FSOUND_GetError), vbOKOnly

Should be:

If Not result Then MsgBox “Record StartSample Error: ” & FSOUND_GetErrorString(FSOUND_GetError), vbOKOnly

  • You must to post comments
0
0

I’ll be working with this sub a lot in the next few days, so there might be several posts on this. “Issue” #3: CopyMemory in FMOD.bas is declared private so you have to change it to public if the sub isn’t in fmod.bas. Here’s CopyMemory for those wondering:

Public Declare Sub CopyMemory Lib “kernel32” Alias “RtlMoveMemory” (Destination As Any, Source As Any, ByVal length As Long)

  • You must to post comments
0
0

[quote="zawy":sno3prlj]I didn’t intend to say it was better than your method, i was trying to say using FMOD for this is better than any other VB method that I know of for recording WAV files. The other methods use enormous DLLs that aren’t on other machines, require the newest Windows Media Player, or are kind of limited, finicky, or just unreliable.
[/quote:sno3prlj]

My method relies with no external DLL, it is VB code only and is intended to be used by FMOD and could easily be used from any other sound lib or homebrew lib : it only write raw pcm data to a riff wave file, like your’s.
Did you really read my code ? ๐Ÿ˜†

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.