Как увеличить битрейт передачи файла через звуковую карту?

#c# #algorithm #audio #naudio #modulation

#c# #алгоритм #Аудио #naudio #модуляция

Вопрос:

Мне нужно передавать файлы, используя только звуковую карту.

мой алгоритм пока основан на манипулировании амплитудным сдвигом (ASK).

Передатчик:
Программа записывает в WAV-файл модулированные данные.
Просто напишите «noise» (создать волну), когда бит равен 1, и напишите «silence» (амплитуда 0) в противном случае.
Количество сэмплов для тишины и шума заранее определено и одинаково в обоих случаях.

Приемник:
Программа начнет запись и дождется сэмпла, который превышает предварительно определенный порог шума.
Как только он обнаруживает шум, он демодулирует записанные сэмплы в файл WAV до тех пор, пока не обнаружит «Конечный сигнал».

протокол:

  1. Первый байт равен 255 и не является частью данных (уведомляет получателя о новом файле).
  2. Затем запишите данные (содержимое файла).
  3. Запишите 4 предопределенных байта, которые указывают на конец сеанса.
  4. Каждый бит передается 3 раза, поэтому в случае ошибки он может угадать правильный бит по двум другим (ECC).

Я использую библиотеку NAudio C # для работы с файлами WAV (запись, воспроизведение, запись, чтение).

Для лучшего понимания я добавил часть своего кода ниже, но, на мой взгляд, вы можете избавить себя от лишних хлопот, я только хочу знать дефекты в алгоритме и как я могу его улучшить.

Передатчик:

 //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);
    }
 }
  

После того, как у меня есть этот файл, он воспроизводится один раз:

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

Приемник:

 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...
}
  

Я написал не все, но в основном приемник ищет 8 * SamplesPerBit образцы шума.
(определяет, зашумлен сэмпл или нет, сравнивая его с пороговым значением шума).
Затем сохраните все остальные данные до тех пор, пока не будет обнаружен конечный сигнал.
Наконец, это сохраняет содержимое в файл.

проблема в том, что для правильной работы мне нужно, чтобы SamplesPerBit был не менее 100. Поскольку имеется 44100 сэмплов в секунду, он записывает около 441 бита в секунду.
И поскольку мои данные утроились, в целом это меньше 20 Байт / сек.

Мне нужно иметь возможность передавать данные со скоростью не менее 1 КБ / сек.

Любые предложения о том, как я мог бы увеличить битрейт, будут очень полезны.

Я думал сделать это с помощью FSK (амплитуда остается неизменной, частота меняется), с помощью класса FastFourierTransform в Naudio, но я не думаю, что так было бы быстрее (возможно, менее подвержено ошибкам).

Ответ №1:

проблемы с вашим подходом

  • слишком долгое молчание или слишком продолжительный шум могут привести к рассинхронизации потока
  • например, передайте 100 МБ нулей, и в итоге количество декодированных битов может отличаться
  • это можно исправить с помощью случайного сигнала синхронизации
  • вы используете шум, который нелегко правильно обнаружить (отсюда низкая скорость передачи)
  • на audio HW у вас есть конденсаторы по пути, поэтому сигнал постоянного тока уничтожается
  • таким образом, коды, использующие сигналы постоянного тока, не подлежат обсуждению, но есть много других, поэтому…

если вы не обязаны СПРАШИВАТЬ, то есть много других возможностей кодирования, которые лучше подходят для этого:

  1. FM

    • например, 0 будет 22050 Гц, а 1 будет 44100 Гц
    • каждый бит может быть закодирован в несколько периодов (не менее 2)
    • также время от времени требуется некоторый сигнал синхронизации (например, 11025 Гц 10 периодов один раз в минуту
  2. PCM

    • например, 4 импульса частотой 44100 Гц равны 1
    • 2 импульса частотой 44100 Гц равны 0
    • и 2 периода тишины между всеми битами
    • для этого не требуется никакого дополнительного синхросигнала

вы также можете добавить сигнал запуска

  • некоторая четкая частота и точная пауза после нее перед передачей данных
  • также вы можете добавить какой-нибудь заголовок перед данными
  • таким образом, приемник знает, какой объем данных ожидать
  • или какую кодировку использовать, если вы хотите поэкспериментировать

[Примечания]

  • вы можете поэкспериментировать с количеством импульсов или частотами
  • Я даю вам быструю настройку, которая все еще должна работать
  • но вы должны протестировать частоту ошибок и настроить ее в соответствии с вашими настройками HW…
  • для надежного определения частоты вам нужно как минимум 2 периода.
  • в шумной среде еще больше…