1

I need to transfer files using only the sound card.

my algorithm so far is based on amplitude shift keying (ASK).

Transmitter:
The program writes to a WAV file the modulated data.
Simply write "noise" (create wave) when the bit is 1, and write "silence" (0 amplitude) otherwise.
The number of samples for silence and noise is pre-defined and equal in both cases.

Receiver:
The program starts recording and wait for a sample that is above the pre-defined noise threshold.
Once it detected noise, it demodulates the recorded samples to WAV file until it detects the "Ending signal".

protocol:

  1. The first byte is 255 and is not part of the data (notify the receiver on a new file).
  2. Then write the data (file content).
  3. Write 4 pre-defined bytes that indicates end of session.
  4. Each bit is transferred 3 times, so in case of an error, it could guess the correct bit by the other two (ECC).

I am using NAudio C# library to handle with the WAV files (record, play, write, read).

For better understanding i added some of my code below, but in my opinion you can save yourself the trouble, i only want to know the defects in the algorithm and how can i improve it.

Transmitter:

//creates file with 44.1kHz sample-rate and 1 channel.
mWaveFileWriter = new WaveFileWriter(tempFile, new WaveFormat(44100, 1));

....

// save to WAV file modulated data the contains bytesData
public void Modulate(byte[] bytesData)
{
    foreach (var dataByte in bytesData)
    {
         // return 8 bit representation of the byte
         bool[] binaryByte = ToBinary(dataByte);

         foreach (bool bit in binaryByte)
         {
             if (bit)
                SaveNoise();
             else
                SaveSilence();
         }
         mWaveFileWriter.Dispose();
    }
}

private void SaveSilence()
{
    for (int n = 0; n < mSamplesPerBit; n++)
    {
        mWaveFileWriter.WriteSample(0);
    }
}

private void SaveNoise()
{
    // writes SamplesPerBit samples
    for (int n = 0; n < mSamplesPerBit; n++)
    {
        float sample = (float)(mNoiseAmplitude * Math.Sin((2 * Math.PI * n * mFrequency) / mWaveFileWriter.WaveFormat.SampleRate));
        mWaveFileWriter.WriteSample(sample);
    }
 }

After i have this file, it is played once:

System.Media.SoundPlayer player = new System.Media.SoundPlayer(tempFile);
player.Play();

Receiver:

WaveInEvent mWaveIn = new WaveInEvent();
mWaveIn.WaveFormat = new WaveFormat(44100, 1);
mWaveIn.DataAvailable += mWaveIn_DataAvailable;

....

void mWaveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    // since it's 16bit sampling, I normalize each 2 bytes to samples of range (-1.0f) - 1.0f.
    float[] samples = ToSamples(e.Buffer);

    ...   // saves data, process it etc...
}

I didn't write all of it but basically the receiver seeks 8 * SamplesPerBit noise samples. (it determines whether a sample is noisy or not by comparing it to the noise-threshold). Then save all other data until it detects the end-signal. Finally it saves the content to a file.

the problem is that for this to work properly, i need SamplesPerBit to be at least 100. Since there are 44100 samples per second, It writes about 441 bits per seconds.
And since my data it tripled, all in all it is less than 20 Bytes/Sec.

I need to be able to transmit the data in at least 1KB/sec.

Any suggestions on how i could increase the bitrate will be very helpfull.

I thought to do it with FSK (amplitude stays the same, frequency changes), with The FastFourierTransform class in Naudio, but i don't think it would be faster that way (maybe less error prone).

flyman
  • 210
  • 4
  • 15

1 Answers1

0

problems with your approach

  • too long silence or too long noise can lead to de-synchronise the stream
  • for example transfere 100MB of zeroes and in the end the decoded bit count can differ
  • this can be repaired with occasional sync signal
  • you use noise which is not easy to detect properly (hence the slow transfere speed)
  • on audio HW you have capacitors along the way so DC signal is destroyed
  • so codes using DC signals are out of questions but there are plenty others so...

if you are not bound to ASK then there are many other coding possibilities there are better for this:

  1. FM

    • for example 0 will be 22050Hz and 1 will be 44100Hz
    • each bit can be coded into few periods (at least 2)
    • also some sync signal is needed time to time (for example 11025Hz 10 periods once per minute
  2. PCM

    • for example 4 pulses of 44100Hz is 1
    • 2 pulses of 44100hz is 0
    • and 2 periods of silence between all bits
    • this does not need any additional synchro signal

you can also add start signal

  • some distinct frequency and exact pause after it before data
  • also you can add some sort of header before data
  • so receiver knows how much data to expect
  • or which coding to use if you want to experiment

[Notes]

  • you can experiment with the pulse counts or frequencies
  • I give you setup that is fast and still should work
  • but you should test the error rates and configure it to match your HW setup ...
  • to safely identify frequency you need at least 2 periods.
  • on noisy environment even more ...
Spektre
  • 49,595
  • 11
  • 110
  • 380