473,287 Members | 1,904 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,287 developers and data experts.

How to play a wave file on the phone (C#) - PART III

PART III: Putting things together

In part I we examined the modem to verify that it supported voice. If so, we took a note about the voice data format that we would use. In the second part, we prepared a wave file and implemented a piece of code in C# to be used by HomeZIX to read the wave file into a buffer. Now, it’s time to put things together to send out that buffer as an audio stream over the phone line to a designated phone number.

In our example here, we are connecting to a voice modem via COM10. It is an old one we got from a local store. We have prepared a wave file: “Houston 8 bit Mono 8kHz.wav” which has the formats: PCM/uncompressed, 8 bits per sample, single channel (mono), 8000 samples per second. We dropped into the HomeZIX’s workplace a virtual switch to control when to start calling the number and playing the wave file. Of course, it’s only for demonstration purposes. In real use, it should call the number and choose appropriate wave file to play according to particular events such as: motion detected, temperature too high, door open, etc…

Download the script to import the C# script to HomeZIX and take a moment to go through the implementation:

Initialize

Expand|Select|Wrap|Line Numbers
  1. public void Initialize()
  2. {   // Required function. DO NOT remove or change the name.
  3.     // Called once when the script start executing.
  4.     string fileName = "C:\\houston 8kHz Mono 8.wav";
  5.     if (!System.IO.File.Exists(fileName)) 
  6.  {
  7.   Debug("Wave file not found.");
  8.   return;
  9.  }
  10.  
  11.     System.IO.FileStream strm = new System.IO.FileStream(fileName, System.IO.FileMode.Open);
  12.     System.IO.BinaryReader rdr = new System.IO.BinaryReader(strm);
  13.     Wave.WAVEFORMATEX wfmt = new Wave.WAVEFORMATEX();
  14.     wfmt.SeekTo(strm);
  15.  
  16.     // Read in the WAVEFORMATEX structure and attempt to open the
  17.     // device for playback.
  18.     wfmt.Read(rdr);
  19.  Debug("Wave file information:");
  20.  Debug("Wave file encoding: " + wfmt.wFormatTag.ToString());
  21.  Debug("Channels: " + wfmt.nChannels.ToString());
  22.  Debug("Bits per Sample: " + wfmt.wBitsPerSample.ToString());
  23.  Debug("Sampling rate: " + wfmt.nSamplesPerSec.ToString());
  24.  
  25.  if ((wfmt.wFormatTag == 1)&&(wfmt.nChannels == 1) && (wfmt.wBitsPerSample == 8) && (wfmt.nSamplesPerSec == 8000))
  26.  {
  27.      uint dataLength = (uint)(rdr.BaseStream.Length - Wave.WAVEFORMATEX.WF_OFFSET_DATA);
  28.      m_whdr = new Wave.WAVEHDR();
  29.      m_whdr.Read(rdr, dataLength, wfmt.nBlockAlign);
  30.   Debug("Wave file data has been read successfully.");
  31.  } else
  32.  {
  33.   Debug("Unsupported wave file.");
  34.   Debug("This example supports only [PCM/Uncompressed], [Mono], [8 bits per sample], [8kHz samples per second] wave files.");
  35.  }
  36.  
  37.     rdr.BaseStream.Close();
  38.     rdr.Close();
  39.     rdr = null;
  40.  
  41.  //Initializing COM port
  42.  m_serialPort = new System.IO.Ports.SerialPort();
  43.  m_serialPort.PortName = "COM10";
  44.  m_serialPort.BaudRate = 115200;
  45.  m_serialPort.DataBits = 8;
  46.  m_serialPort.StopBits = System.IO.Ports.StopBits .One;
  47.  m_serialPort.Parity = System.IO.Ports.Parity.None;
  48.  m_serialPort.Handshake = System.IO.Ports.Handshake.None;
  49.  m_serialPort.DtrEnable = true;
  50.  try
  51.  {
  52.   m_serialPort.Open();
  53.   Debug("COM port is ready.");
  54.  } catch
  55.  {
  56.   Debug("Error opening the COM port.");
  57.  }
  58.  m_talking = false;
  59. }
We have seen this function in Part II. This time we added initialization for the COM port. In our case here: serial COM10 is connected to our external voice modem. Most modems have an auto detect feature for a serial connection. So the settings here: 115200bps, 8 data bits, 1 stop bit, no parity, no handshaking would likely work. However, check the modem's manual to make sure you set them correctly. Hyper Terminal is a handy tool to test your setup approach.

Execute

This function detects if the virtual switch has been turned on. If so, it starts the calling process. Because this function is called every second, we don’t want to monopolize the processing time of the main program by processing the modem connection here. Instead, we spawn another thread to do that job.

Expand|Select|Wrap|Line Numbers
  1. public void Execute()
  2. {   // Required function. DO NOT remove or change the name.
  3.     // Called every second.
  4.  int status = GetStatus("Virtual switch..0.0");
  5.  if ((m_virtualSwitchPreviousState == 0) &&(status > 0))
  6.  {
  7.   if (!m_talking)
  8.   {
  9.    m_talking = true;
  10.    m_phoneThread = new System.Threading.Thread(new System.Threading.ThreadStart(WaveToPhone));
  11.             m_phoneThread.Start();
  12.   }
  13.   m_virtualSwitchPreviousState = status;
  14.  }
  15.  if ((m_virtualSwitchPreviousState > 0) &&(status == 0))
  16.  {
  17.   m_talking = false;
  18.   m_virtualSwitchPreviousState = status;
  19.  }
  20. }
This thread has 3 parts: preparing the modem, sending wave data, and finally terminating the session.
Preparing the modem: These are commands to put the modem in voice mode with our selected voice data encoding format. When a command has been sent to the modem, the script waits for the response. We didn’t check the response here since we know it works (from going through Part I.) We simply print out the debug string. The last steps of this phase is to call the number (“ATDT number”) and switch the modem to the sending voice data mode (“AT+VTX”)

Expand|Select|Wrap|Line Numbers
  1. private void WaveToPhone()
  2. {
  3.  if ((m_serialPort != null)&&(m_serialPort.IsOpen))
  4.  {
  5.   SendCommand("ATZ");
  6.   GetResponse(1, true);
  7.   SendCommand("AT+FCLASS=8");
  8.   GetResponse(1, true);
  9.   SendCommand("AT+VSM=128,8000");
  10.   GetResponse(1, true);
  11.   SendCommand("ATDT" + m_phoneNumber);
  12.   GetResponse(60, false);
  13.  
  14.   SendCommand("AT+VTX");
  15.  
  16.   System.Threading.Thread.Sleep(500);
  17.   SendVoiceData();
  18.   System.Threading.Thread.Sleep(1000);
  19.   SendVoiceData();
  20.   System.Threading.Thread.Sleep(1000);
  21.   SendVoiceData();
  22.   System.Threading.Thread.Sleep(1000);
  23.  
  24.   byte [] terminator = new byte [2];
  25.   terminator[0] = 0x10;
  26.   terminator[1] = 0x03;
  27.   m_serialPort.Write(terminator, 0, 2);
  28.  
  29.   SendCommand("ATH");
  30.  }
  31.  m_talking = false;
  32. }
Sending the wave data.

In the Initialize function, we already read the data into the buffer from a wave file. It’s time now to transfer that buffer as an audio stream to the modem. However, because the modem likely cannot handle large amount of data at once, we send data in chunks of 1024 bytes each. This greatly improves the total throughput ensuring smooth voice on the other end. In our example there, we also repeat the same data buffer 3 times.

Expand|Select|Wrap|Line Numbers
  1. private void SendVoiceData()
  2. {
  3.  if ((m_whdr == null)||(!m_serialPort.IsOpen)) return;
  4.  int offset = 0;
  5.  int blockSize = 1024;
  6.  int dataLength = m_whdr.data.Length;
  7.  if (dataLength == 0) return;
  8.  try
  9.  {
  10.   Debug("Start sending WAVE data...");
  11.   while (true)
  12.   {
  13.    m_serialPort.Write(m_whdr.data, offset, blockSize);
  14.    if (blockSize < 1024) break;
  15.    offset += blockSize;
  16.    if (dataLength - offset < 1024) blockSize = dataLength - offset;
  17.   }
  18.   Debug("Done sending WAVE data.");
  19.  } catch
  20.  {
  21.   Debug("Error sending WAVE data.");
  22.  }
  23. }
Terminating the call.

Once the wave data has been sent, we terminate the connection by: sending 0x10 0x03 to the modem to switch off the sending mode, and then hang up the phone by sending “ATH”. Note that if you plan to have multiple scripts handling different wave files for different events, you will have to close the COM port here as well.
Sep 7 '07 #1
6 29033
hi,
one thing i wana know, from where can i get Memory.CS and Wave.CS.
please help if any body know.
Nov 3 '07 #2
After sending ATDT6523823, the code is sending voice directly without knowing whether the dialing number is pick up or not. How can I do to send wave only if the dialing number is pickup?

Best regards,

Veasna
Nov 8 '07 #3
good code , but how can i write it by python? tks
Apr 2 '08 #4
please give me sample code for testing are you using third party control in this sample becasue it is not compiling in C# environment
Jun 16 '10 #5
can u give the source code?

plz specifically tell the modem name used in it so that i can buy.
May 29 '11 #6
Heya, great artical. But it's incomplete probably because of links. I can't use the wav object. That's no biggie but can someone please provide a more complete sample? Or is there a c# class i can use that can I can substitute? Right now I'm getting the modem to call but as soon as I write the connection drops my phone.
May 31 '11 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: Ashish | last post by:
I wanted to make a Java application which would dial a telephone number using the modem. When the person on the other end lifts up the telephone (answers the phone), the application should start...
1
by: webstar | last post by:
hi, could you please tell me how to play a small wave file if a button is pressed. or if there is another format that is easer then use that instead of wave. thanks matt
4
by: Dennis M. Marks | last post by:
This is a simple question. How do I preload a wave file and play it on command? -- Dennis M. Marks -----= Posted via Newsfeeds.Com, Uncensored Usenet News =----- http://www.newsfeeds.com -...
4
by: vikram | last post by:
in a stereo type of wave file i want to know what is this left & right info in a wave file??? how do i read the left & right info from a .wav file to a buffer..
1
by: DaniloAlmeida | last post by:
Hi everyone, How are you ? Happy new year for all !!! Well I want to know how can I find some data like a tone in a recorded wave file in WindowsPCM format in 11kHz - 8bits. This file(s)...
9
by: Morris Neuman | last post by:
Im working with VS 2005 and trying to use a Hyperlink field in a datagrid to play a wave file that is not located in the website folders but is in a plain folder on the same machine, windows 2003...
2
by: Lint Radley | last post by:
Hello Everyone, I've seen online many examples online using a DLLImport of WinMM.dll to a WAVE file in C#/.NET. I haven't seen any methods in the .NET Framework - does it not exist, or am I...
2
by: homevista | last post by:
Our goal here: We want the PC to call a designated phone number when something happens, and report it in easy-to-understand spoken audio snippets which are saved in the form of pre-recorded wave...
1
by: homevista | last post by:
Part II: Wave file - How to read to a buffer Wave (or Wav) is the standard format for storing audio data on the PC. As software developers, we are interested in the internal structure of the file...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.