I am trying to set up a program to phone members of my church and play a wave file with the latest news and events.
I think I need a tapi solution to this but I'm more accustom to Access then VB6. I have made a few basic programs but this one is going to be a challange.
So here's what I need to do.
1. Dial the members number.
2. Wait for an answer.
3. Deliver a message via wav file.
4. Hang up and repeat the process.
Has anyone found any solution to this? I am using AT commands to dial the phone. I can hear junk in the modem when the phone is answered. Can also hear tones when the phone presses a key. But really no idea how to start to go about playing the wav file. Any sample code or insight would be greatly appreciated.
The sound you have to send/receive through the comm port as wave data (NOT through the sound card as you may expect!).
So you have to convert your data to propper format, probably something like Mono, 8 Bit, 11025Hz, and then send that binary data (the sound) through the comm port.
When you want to record, then you have to give the AT command for recording, and start saving the data received to a wave file.
Also, there are not many modems that support Voice, so make sure your modem supports Voice first, if not you many have to buy one.
Thank CVMichael i just made a ton of progress thanks to you. I can now dial, answer, and play tones. I can even recieve tones back. But playing the .wav file I'm kinda lost. Pretty sure I must somehow stream to data through but I really dont know how to do this. Any code examples? Or direction where to look?
You have to tell it what format to transmit or receive, for that you use the command AT+VSM.
If you do "AT+VSM=?" you get all the possible options that your modem can support, something like:
Code:
AT+VSM=?
1,"UNSIGNED PCM",8,0,8000,0,0
129,"IMA ADPCM",4,0,8000,0,0
130,"UNSIGNED PCM",8,0,8000,0,0
140,"2 Bit ADPCM",2,0,8000,
141,"4 Bit ADPCM",4,0,8000,0,0
So, from that pick a format that is easy for you to play and record, so from the list, I would pick either #1 or #130 (they seem to be the same).
So give the command "AT+VSM=1" to tell it you want to use sound format #1.
Then record a wave file with a sound recorder in that format, and send the wave data (the file) through the comm port as binary data.
When you send the wave data, you have to remove the wave header, if you don't know how to do that I don't think it's a big deal if you do send the header also.
To get familliar with wave header & data, see this: VB6.0 – Sound and DirectXSound Tutorial
The commd "AT+VLS=?" will list the options to choose from where to send/receive the sound. Each letter means something, but I don't remember what it means for sure. For example "M" I think it means microphone (and you don't want to choose that by the way).
So to send data (play sound), you should give these commands:
Code:
AT+FCLASS=8
AT+VLS=1
AT+VSM=1
AT+VTX
and then the wave data
Last edited by CVMichael; Jan 23rd, 2012 at 10:13 AM.
Code:
AT+FCLASS=8
AT+VLS=1
AT+VSM=1
AT+VTX
and then the wave data
My problem is when I come to the "and then the wave data" is where I dont know where to begin. I am using System.IO.Ports and I see stuff that looks like it "should" work (.BaseStream, .BytesToRead, .BytesToWrite) but I cant figure out how to use them. I keep getting the error "Value of type 'Byte' cannot be converted to 1-dimensional array of Byte"
So I guess I am looking more for examples/help with how to stream data since I obviously dont know what I am doing with it.
***edit: I am looking into your "VB6.0 – Sound and DirectXSound Tutorial" link now.
Last edited by PALMER; Jan 23rd, 2012 at 10:33 AM.
I have tried them all but nothing seems to play other than silence and some crackles here and there. Im thinking maybe my wav file is not the right format? I have tried changing that too but I dont think Im even doing that right.
"at+fclass" is 8 for Voice, I am pretty sure about this.
for "at+vls", I forgot to ask what modem you have? (the model). You have to find documentation on your modem, to find out what each option in the list of "at+vls" means.
Im also thinking my streaming the data is not right.
Code:
Private Structure FileHeader
Dim lRiff As Long
Dim lFileSize As Long
Dim lWave As Long
Dim lFormat As Long
Dim lFormatLength As Long
End Structure
Private Structure WaveFormat
Dim wFormatTag As Integer
Dim nChannels As Integer
Dim nSamplesPerSec As Long
Dim nAvgBytesPerSec As Long
Dim nBlockAlign As Integer
Dim wBitsPerSample As Integer
End Structure
Private Structure ChunkHeader
Dim lType As Long
Dim lLen As Long
End Structure
Private Function WaveReadFormat(ByVal InFileNum As Integer, ByRef lDataLength As Long) As WaveFormat
Dim header As FileHeader
Dim HdrFormat As WaveFormat
Dim chunk As ChunkHeader
Dim by As Byte
Dim i As Long
FileGet(InFileNum, header)
If header.lRiff <> &H46464952 Then Exit Function ' Check for "RIFF" tag and exit if not found.
If header.lWave <> &H45564157 Then Exit Function ' Check for "WAVE" tag and exit if not found.
If header.lFormat <> &H20746D66 Then Exit Function ' Check for "fmt " tag and exit if not found.
' Check format chunk length; if less than 16, it's not PCM data so we can't use it.
If header.lFormatLength < 16 Then Exit Function
FileGet(InFileNum, HdrFormat) ' Retrieve format.
' Seek to next chunk by discarding any format bytes.
For i = 1 To header.lFormatLength - 16
Try
FileGet(InFileNum, by)
Catch ex As Exception
End Try
Next
' Ignore chunks until we get to the "data" chunk.
FileGet(InFileNum, chunk)
Do While chunk.lType <> &H61746164
For i = 1 To chunk.lLen
FileGet(InFileNum, by)
Next
FileGet(InFileNum, chunk)
Loop
lDataLength = chunk.lLen ' Retrieve the size of the data.
WaveReadFormat = HdrFormat
End Function
Private Sub btnSendWav2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendWav2.Click
Dim WaveFmt As WaveFormat
Dim FileNum As Integer
Dim lDataLength As Long
Dim Buffer() As Integer
' open the wave file
FileNum = FreeFile()
FileOpen(FileNum, "C:\smallstep.WAV", OpenMode.Binary)
' read the header, and get the chunk size (data length)
WaveFmt = WaveReadFormat(FileNum, 9300)
' resize our buffer to hold the entire wave data (DataLength is in Bytes)
ReDim Buffer((lDataLength \ 2) - 1)
' read the wave data from the file into our buffer
FileGet(FileNum, Buffer)
FileClose(FileNum) ' close the file
TextBox2.Text = Buffer.ToString
End Sub
In this example, it is basically your code after I tried to convert it to vb.net. Im basically just trying to dump the stream data into TextBox2.Text
And this is the .wav file I am trying to use. http://www-mmsp.ece.mcgill.ca/docume...A/truspech.wav
Last edited by PALMER; Jan 25th, 2012 at 12:04 PM.
Also, step through the code, and see it if passes these lines:
Code:
If header.lRiff <> &H46464952 Then Exit Function ' Check for "RIFF" tag and exit if not found.
If header.lWave <> &H45564157 Then Exit Function ' Check for "WAVE" tag and exit if not found.
If header.lFormat <> &H20746D66 Then Exit Function ' Check for "fmt " tag and exit if not found.
' Check format chunk length; if less than 16, it's not PCM data so we can't use it.
If header.lFormatLength < 16 Then Exit Function
I forgot i changed some things to try out. 9300 was just a random number in my head.
Code:
Private Structure FileHeader
Dim lRiff As Integer
Dim lFileSize As Integer
Dim lWave As Integer
Dim lFormat As Integer
Dim lFormatLength As Integer
End Structure
Private Structure WaveFormat
Dim wFormatTag As Short
Dim nChannels As Short
Dim nSamplesPerSec As Integer
Dim nAvgBytesPerSec As Integer
Dim nBlockAlign As Short
Dim wBitsPerSample As Short
End Structure
Private Structure ChunkHeader
Dim lType As Integer
Dim lLen As Integer
End Structure
Private Function WaveReadFormat(ByVal InFileNum As Short, ByRef lDataLength As Integer) As WaveFormat
Dim header As FileHeader
Dim HdrFormat As WaveFormat
Dim chunk As ChunkHeader
Dim by As Byte
Dim i As Integer
FileGet(InFileNum, header)
If header.lRiff <> &H46464952 Then Exit Function ' Check for "RIFF" tag and exit if not found.
If header.lWave <> &H45564157 Then Exit Function ' Check for "WAVE" tag and exit if not found.
If header.lFormat <> &H20746D66 Then Exit Function ' Check for "fmt " tag and exit if not found.
' Check format chunk length; if less than 16, it's not PCM data so we can't use it.
If header.lFormatLength < 16 Then Exit Function
FileGet(InFileNum, HdrFormat) ' Retrieve format.
' Seek to next chunk by discarding any format bytes.
For i = 1 To header.lFormatLength - 16
Try
FileGet(InFileNum, by)
Catch ex As Exception
End Try
Next
' Ignore chunks until we get to the "data" chunk.
FileGet(InFileNum, chunk)
Do While chunk.lType <> &H61746164
For i = 1 To chunk.lLen
FileGet(InFileNum, by)
Next
FileGet(InFileNum, chunk)
Loop
lDataLength = chunk.lLen ' Retrieve the size of the data.
WaveReadFormat = HdrFormat
End Function
Private Sub btnSendWav2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSendWav2.Click
Dim WaveFmt As WaveFormat
Dim FileNum As Short
Dim DataLength As Integer
Dim Buffer() As Byte
' open the wave file
FileNum = FreeFile()
FileOpen(FileNum, "C:\smallstep.WAV", OpenMode.Binary)
' read the header, and get the chunk size (data length)
WaveFmt = WaveReadFormat(FileNum, DataLength)
' resize our buffer to hold the entire wave data (DataLength is in Bytes)
ReDim Buffer((DataLength \ 2) - 1)
' read the wave data from the file into our buffer
FileGet(FileNum, Buffer)
FileClose(FileNum) ' close the file
TextBox2.Text = Buffer.ToString
End Sub
ok fixed a bunch of stuff and made the Integer to Short and Long to Integer changes you suggested. I ran the code and it does stop at If header.lRiff <> &H46464952 Then Exit Function
I think you also have to add something like "<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _" in front of the declaration of the structure
Worst case schenario, you can read the entire wave file in a byte array together with the header, and just send that through the comm port.
The header will become some "junk" sound, but because it is only a few bytes, it will sound like a short "tick" for a few milliseconds. After that will come the wave data.
this is a very old problem form aout of the ark. no pun intended
The problem is in 6 parts
(1) can you dial a phone number?
(2) can you asks a question and respond to the answer
(3) reguardless of (2) can you shout down the phone
(4) can you respond to a hangup
(5) reguardless of (4) can yoy hangup
(6) Can you go back and do it again
I think you can because i do some of this for a phone redirecter system at home
in the uk you must be in the house of the phone you wish to redirect to do so.
I simply have an old pc that wakes up if power is restored to it and it is tasked
with checking an email account when the account contains a message the machine uses
rasdial to dialout and attempt to connect to a server, the server does not exist and the call fails
leaving me with a redirected telephone - servernumber is *21*telephonenumber#.
The call failure prompts radial to hangup!
its a quick fix for me!
I used to do what you want to do as a script that caused the old modem to dial a number
I used spearate batch files in a directory
so home.bat was at#d 12345 and a wait() that waited for a key press to hangup
i would then talk - entering any key into the dosbox whyen i wanted to hang up!
the same technique would work for you i think - but i will need to get the big box out - we do not have modems anymore - all broadband now!
its really a question of holding the line while you talk.
Hard to describe... but now i can get it to send a stream of a very quiet data-sending type tapping noises. Almost as if it is playing very quiet morse code.
@palmer you should only hear the dialtone then the dialer dialing then the voice say in hello hello no a nother bloody fax
unless that is you are in voice mode then you just hear hello hello maud its for you!
End result i need is:
1. program calls a number
2. person answers (or not, goto step 5)
3. program plays a message that says press "1" to confirm reciept of message.
4. person presses 1
5. program hangs up and marks call as complete or incomplete.
What i have so far: . program calls a number
2. person answers (or not, goto step 5)
3. program plays a message that says press "1" to confirm reciept of message.
4. person presses 1
5. program hangs up and marks call as complete or incomplete.
So far basically I have these steps i send to serialport
AT+FCLASS=8 set voice mode
ATDT*995185551234 dial number (i hear it dial out and my phone rings)
AT+VLS=1 set line features
AT+VSM=1 set sound capability
AT+VTX set to transfer
System.Byte[] Byte array of the .wav file
on my phone i can hear ...... . . . . .... . . . .. . . . . . .... ...
Kind of like very quiet static blips.
ok. I've got my app calling my phone and playing a crackly staticy message. You can make out the words... but it is definatly not good enough. I think i have tried every available setting... except the one that works.
I could record it on my cell phone but it saves as a funky format (.qcp) and vbforums wont let me attach it. Trying to convert it for you.
So another testing i did is that i can use windows dialer and call my phone with a headset. I can then open a .wav file and play it. I then bend the mic into the headset speaker it plays fine. Clear, correct speed, and everything. But obviously i dont want to "rig it". This way is using the sound card. Do I need to use the sound card to de/encode and buffer it correctly??
These are the methods I tried using to stream the sound in. Serport2 is the serial port.
Method 1
Code:
Dim list As New List(Of String)
Using r As StreamReader = New StreamReader("C:\test3.wav")
Dim line As String
line = r.ReadLine
Do While (Not line Is Nothing)
list.Add(line)
serport2.Write(line)
line = r.ReadLine
Loop
End Using
Method 2
Code:
Dim oFile As System.IO.FileInfo
oFile = New System.IO.FileInfo("c:\test3.wav")
Dim oFileStream As System.IO.FileStream = oFile.OpenRead()
Dim lBytes As Long = oFileStream.Length
If (lBytes > 0) Then
Dim fileData(lBytes - 1) As Byte
oFileStream.Read(fileData, 0, lBytes)
serport2.Write(fileData.ToString)
oFileStream.Close()
End If
Both methods product the same result. Words with static.
Correction... method 2 does not play anything. I started with method 2 and ended up with method one. So ignore method 2. My brain is getting fried doing this.
ReadLine should be used only for text files, wave is binary. So method 2 should be the one that works.
Having said that, why do you have "fileData.ToString", you can't pass the binary data?
' Open a file that is to be loaded into a byte array
Dim oFile As System.IO.FileInfo
oFile = New System.IO.FileInfo("c:\test3.wav")
Dim oFileStream As System.IO.FileStream = oFile.OpenRead()
Dim lBytes As Long = oFileStream.Length
If (lBytes > 0) Then
Dim fileData(lBytes - 1) As Byte
' Read the file into a byte array
oFileStream.Read(fileData, 0, lBytes)
serport2.Write(fileData, 0, lBytes)
oFileStream.Close()
End If
I was using a different function serport2.write(string) then I looked and found it does have the ability to take bytes.
Yes. The way i was streaming it was wrong. The sound comes through clear and no static. Once I fixed up method 2 to send the data as bytes instread of string it worked. I dont know why I was overlooking that. It never dawned on me that .tostring was changing the binary. I just figured it was sending it all in one big chunk.
Although after further testing it does matter what format the sound is in. Seems as though i still need to stay around 8000Hz, 8bit, Mono, 7kb/sec. Surely that is do to the AT+VSM
1,"UNSIGNED PCM",8,0,(7200,8000),(0),(0)
128,"8-BIT LINEAR",8,0,(7200,8000),(0),(0)
129,"ADPCM",4,0,(7200,8000),(0),(0)
130,"UNSIGNED PCM",8,0,(7200,8000),(0),(0)
131,"ULAW",8,0,(7200,8000),(0),(0)
132,"ALAW",8,0,(7200,8000),(0),(0)
133,"LINEAR",16,0,(7200,8000),(0),(0)