A QAM soundcard modem.

Able to use the soundcard to send and receive data up to about 400kbs by implementing the QAM modulation scheme.
Data can be two way or one way. Any sort of data can be sent , Files, Video, Audio, WebPages etc.
Make a transmitter and you have your very own broadcast station.


Speeds up to 400kbs with a sound card.
QAM16 and QAM64
Eight state TCM encoding.
Between 1% and 50% Interleaved RS forward error correction.
Blind equalization, frequency tracking.
Blind carrier frequency and symbol rate detection.
Packet type of data structure.
Able to perform multimedia streaming (sound and video).
Able to send files in continuous rotation with unused bandwidth (sending of web page type content).

The story:
this program is something I have wanted to create ever since I was a child when I heard about using different phases and amplitudes to send data over telephone lines. QAM which stands for quadrature amplitude modulation is exactly what this is. compared to modulation schemes like FSK (frequency shift keying), QAM in contrast is unbelievably complicated. QAM's advantage though is that this is much more efficient than FSK. QAM is used in satellite TV, digital TV, telephone modems etc.

My specific aim was to create an application to send data using a simple FM transmitter from one computer to another computer using a computer sound card. what I had in my mind was to have one computer send data via a small transmitter while another one received it. I was not concerned about latency at all. I was also not concerned about fast turnaround of a radio frequency channel.

As far as I am aware no one has made a program like this for a computer's sound card, and I'm just too excited to spend a long time writing a manual and checking for all the bugs in the program, and given that no one is paying me a cent to do this I don't believe that I should. It has taken me about six months to create the first version of the program, and about 2.4years to create the most recent version of the program. there are programs that are able to send data using the sound card but normally they use FSK which means they are unbelievably slow, also they tend to be aimed towards HAM operators that transmit very long distances over frequencies that contain a lot of noise or fade, ie HF. there are a couple of programs that don't use FSK the ones I know of are WinDrm, Dream, DIGTRX, these use OFDM which is from what I read superior to QAM over fading channels and is a very interesting modulation scheme indeed. Apparently Charles Brain G4GUO wrote a program for sending QAM using the sound card but I know nothing of it. None of these programs however will allow you to send video and audio at 400kb/s. So clearly there was a need for a program like mine. Also I can't believe no one has done something like it before, so I would like to be the first, if at all possible. This also gives me an incentive to put it on the web quickly.  True, theirs I'm sure will be far more robust being sent via HF radio waves than mine, but maybe it will spark some interest in programs that use QAM and OFDM instead of FSK, and that is good.

Streaming media:
Version 2 and below used unreal media server to stream video media. Version 3 and above I have switched to ASF datastreams served by  HTTP servers. VLC can do this. VLC at the moment has problems with its encoders. The codecs that seem to work ok on VLC are H-264/ACC  I hope they fix this problem soon and make all of them work just as well.

with unreal media server you need to download both the server and the live server to stream video.  JQAM version 2 and below imitates a unreal media TCP server which unreal media player can connect to. if you have not changed any of the TCP settings in my program, then, unreal media player will require localhost:1579 , unicast, TCP, live source alias=video. unreal media server will require setting up to have a live source with a alias called "video"

The main receiving window. Receiving a station.

   The ubiquitous constellation display and also a frequency spectrum display.

        TV being streamed.

The demodulator (receiver) is now totally automatic. The demodulator is now able to detect all the settings the modulator can choose. On the demodulator side all one has to do is to press the start button and and the program will do the rest. this should make the set up of the demodulator easy. on the modulator side the set up is pretty much the same for all versions of the program. 

for video streaming from one end of the house to the other (using 48000Hz soundcards) a common setting I use for the modulator set up is
alpha=0.1    (Root raised cosine variable. wikipedia will explain all)
gamma=0.54 (fraction of a wave per constellation point. theoretical limit is 0.5. don't go that low though)
modfir=500 (number of terms for modulation convolution, bigger is better but increases latency)
constellation type=QAM64
RS error percent=20%
frame period=300
interleaving length=400    (this is big and produces a lot of latency)
the data rate of this works out to be ((100-20)/100)*(11300/0.54)*5=83.7kbs.

 J-QAM user manual V2. (a  users manual for version 2.0a)
 J-QAM user manual v1.1 ish. (a  users manual for version 1.1 ish)

Version 2 and above has the ability to be able to send web pages, sound files, video clips, programs, and whatever multimedia else you would like to send in continuous rotation.  It allows you to send other data in addition to streaming media or whatever in previously unused bandwidth. It makes one way transmission of data seem more interactive than just watching TV or audio and can contain information about the station.

In version 2.0a I added a frequency spectrum display, it looks pretty but if you really want to know what the frequency spectrum really looks like then I suggest you use a program like spectrum laboratory to see how the settings change what the wave looks like. Here is an example of what the frequency of the wave looks like after it has traveled from one end of my house to the other through a little FM transmitter.
The reason it slopes down is due to high frequencies being attenuated in the transmitter and in the receiver. the equalizer in my program corrects this.

Getting the signal from one computer to another:

there are two main ways to do this, either connect the sound cards up directly using some wire, or transmit the sound via radio waves. the wire method is fairly self-explanatory.  For the radio transmitter method, most any transmitter should do. There are a plethora of one and two transistor FM transmitter circuits on the Internet, any one of these that can be plugged into the sound card should allow you to test my program.


Version 2 is quite different in its underlying structure from the past versions. below are two interactive pictures that explain the structure.
(Click on the components in the images!!!)

The Modulator.


The Demodulator.


For historical reference the block structure for versions around 1.2 are here.


For more information on what I have written on how digital QAM works click the links below. Also, checkout wikipedia's QAM page.
 The basic idea of digital QAM. (A discussion on how digital QAM works)
 Recovering Carrier And Symbol timing. (A discussion on how to recover carrier and symbol timing)

I have now done a long distance test of over 1km. I used a 1W transmitter using J-QAM version 1.1a. The terrain in between the transmitter and receiver was relatively hilly so the signal was relatively weak at the receiver. I tested it using QAM16 at freq=7kHz, alpha=0.35, gamma=0.75, making a speed of 28.8kbs with a bandwidth of 14kHz. the decoded signal had a very acceptable mean squared error (MSE) although from time to time it fluctuated quite a lot. my program said it had an MSE most of the time of around 10ish, and occasionally would fluctuate to values in the range of 40ish. My MSE is the mean squared error of the received path to the closest codeword path defined by the TCM scheme, also the numbers don't really have any known units. Multipath was not a problem for this test as I thought it might be. the main problem was little bursts of errors causing packets to be lost. This is a major problem for any practical application, especially for one-way communication as in my test. I was streaming audio in my test and the little bursts of errors caused very annoying interruptions in the audio stream. on making this program I was hoping that TCM would cure all the errors during transmission, I did not really think about burst errors. From what I've read TCM corrects for AWGN (the hiss heard on radio's) well, but it's unable to correct any burst errors. this isn't really surprising, for burst errors if you have only one-way communication, you need to somehow spread the data out temporally. Since version 1.1a I have added interleaved BCH forward error correction to version 1.2a, this should resolve the burst error problem totally at the expense of using 25% of the bandwidth. I have yet to test this out, although hopefully I should do it shortly.

In version 1.3a I have rewritten the data formatter and deformatter routines. This was needed as the error correction of version 1.2a was flawed. The scrambler is now an additive one. The error correction is RS with a block length of 255. The most important thing with the new code, is that it takes advantage of the synchronous nature of QAM. The "RS Error Percent" setting tell the program how much bandwidth to use for error correction. The "Frame Period" is how often sync frames are sent, they are 5bytes long and are sent every "Frame Period"*255 bytes. "Interleaving Length" is the number positions the interleaver can take, it acts like a buffer to spread data temporally, this resolves burst errors, it causes data to be delayed by "Interleaving Length"*"Interleaving Length" byes. I have only done a test from one end of the house to the other using little FM transmitters, but from what I have seen it looks good. Still, only longer distance tests really finds the things that need to be worked on.

Version 1.3.1a I have changed the audio library for one written by Volker Fischer. It doesn't use Directsound but is seems more robust and doesn't miss an audio sample. Saves 500k on memory too. Couple of other minor changes as well.

Version 1.3.2a Changed the acquisition routine to a different type, more systematic. More immune to burst errors. Uses slightly lower CPU. Interesting modification and is more standard for QAM, the equalizer no longer needs to track the symbol timing this is done by a modified Gardner algorithm. The receiver only initially adjusts it's frequency to the transmitter after witch time it has a accuracy of about 1/1000th of a Hertz, directed decision phase tracking adjusts the rest during normal operation. I can easily get 80Kb/s wma stereo audio from one end of the house to the other using this one.

Version 2 has total blind recovery of an arbitrary signal produced by version 2 of my program. lots of other bits and pieces also done on it. The first builds of this version had a couple of little mistakes so hence only third build is available.

  • 06/08/08:
    Tested JQAM v2 over a 1Km distance. A superb test with outstanding results. 81.5kb/s throughput. Read all about How the 1km JQAMv2 test went.
  • 16/4/09:
    Reported to me that someone used this program to send signals on a 22.4km round-trip via a repeater station. Can anyone beat this?
  • 29/4/10:
    36km trip through the sound channel of an ATV repeater.

Version 2 has some bugs when running on some computers, it drops soundcard buffers causing loss of synchronization and threads can stomp on each other. Also, I am unable to compile this version anymore.

I was writing an OFDM soundcard modem which would have probably been up and running in a month or two (from November 2008) but I'm putting that on the back burner for the moment. Although more or less written, I am not interested in putting the effort into bringing it to release. So don't expect this burst modem any time soon.

The next version of J-QAM has now been written, version 3. It is been written as two distinct objects. One is a graphical user interface (GUI) written using Nokia's QT libraries (4.6.1). To save space I have not included any of the QT libraries necessary, if you don't already have them installed you need to download them and install them before JQAMv3 GUI will work, they can be found at http://qt.nokia.com/downloads/downloads#lgpl. If you run Windows and don't have them and don't want to download the full library from Nokia, then I've packaged just the ones you need in my download section. Unzip the library file and place the DLLs in JQAM's file directory. If I see that most people don't have QT4 libraries I may decide to include them in the JQAMv3 setup package. The GUI does little more than look pretty. The other part is the modem itself, and is a shared library object, LibJqam. This is the real key in making J-QAM work. It is a total rewrite of the core modulator and demodulator parts from scratch. This new version of J-QAM is not compatible with version 2 due to stronger error checking. I've fixed numerous bugs that the last version of J-QAM had. It's the cleanest most professional piece of code I have ever written. However, due to my experience with J-QAM so far, I am not releasing as GPL/LGPL. I am releasing a free demo version and a paid version. This new version can run on Linux and Windows. Version 3 allows you to write your own front-end programs by using LibJqam with minimal code. If you are interested in writing your own front-end programs then see http://homepages.paradise.net.nz/peterfr2/libjqamv3api.html. I am yet to write documentation for JQAMv3, and when this gets done is all dependent on free time. There is however a little on getting started with rigging up VLC with JQAMv3 this can be found gettingstarted.html. For the demo version you can test out streaming audio by choosing AAC bitrate 15kb/s channels 1 and sample rate 11250 and no video in VLC, that's slow enough to get through the 17kb/s demo limit. There are a few updates planned for v3 so stay tuned. The change log for v3 can be found at JQAMv3 Change Log

11/4/10: JQAMv3 now has the ability to send and receive files. It's based around streams where each stream is sent simultaneously. Every stream you assign a priority to. File streams are only sent when there is no crucial data like video and audio demanding immediate attention. This means there is no penalty for adding a file stream or two to your transmission. Stream one has a special characteristic that if you add a file called index.html, index.htm, or index.shtml and associated dependencies on the HTML page you will be able to advise the receiver on details about who you are, what your station is, or any other sort of multimedia information. When stream one is fully transferred and the index page found, a little image of a Globe lights up and can be clicked to open up the HTML page to view the multimedia information.
Also with this update I have added a few features that amateur radio people hopefully will find useful. I have added a simplex mode, whereby upon starting JQAMv3 it is initially set to a listening mode. Then when the user wants to transmit files, with the click of a button, JQAMv3 will switch to a transmission mode, send the files and return back to a listening mode. I have uploaded a little video clip demonstrating what this looks like from the receiving end, you can watch this at recfileseg.mp4.

14/5/10:  I have added to JQAMv3 the ability to set a frequency offset. This means you can produce an ultrasonic subcarrier. You can also move the carrier frequency around pretty much anywhere. The picture below shows a real-life screenshot of an 18 kHz JQAM subcarrier with audible mono music, sent using JMPX in mono for the audio pre-emphasis, JQAMv3 for the ultrasonic sub carrier, and the transmitter as in 1km JQAM test.html. The net data rate is about 10 kb/s.

Linux now has Jack support and Windows WaveOut. I added WaveOut because on my main computer when running Windows, directsound every minute or so would drop a frame which becomes quite noticeable when using high frequency carriers. Whilst quite inaudible, the 5 s skip would cause a loss of lock. Directsound is still supported.

Jack is very handy to use. Using QJackCtl you can see if any buffers have been dropped and how close you're coming to maxing out the CPU time given to JQAMv3.

I am aware that the Linux port might be tricky to get working because I'm only supplying binaries. If you have any good ideas here let me know. The Linux versions were compiled on a 32-bit Mandriva 2010,, gcc 4.4.1, and a Gigabyte GA-MA785GMT-UD2H with a Phenom II  X4.

8/6/10: I have now added a fast FIR pre-equalizer to the demodulator. This seems to help acquisition of hard to get signals where the frequency response of the channel is far from being flat.Visually, what it does can be seen from the following two pictures.

In addition I have also included the ability to boost high frequencies at the expense of low frequencies on the modulator side.

OGG container format is now supported. This means you can use Voribis and Theora compressors which are two very good codecs.

Also, to help getting the perpetually infuriating VLC to work, on the modulator side I've added a window that hopefully should help make this an "easier" experience.

Lastly this has been a huge amount of effort on my part, creating such a program has taken me 2.5years so far!!!


Jonti Olds
8 June 2010


Jonti. Last modified Fri, 17 Mar 2023 06:59:53 GMT.