Передача звука по сети

Тема в разделе "Arduino & Shields", создана пользователем atlo, 21 мар 2017.

  1. atlo

    atlo Нерд

    Добрый день!
    Помогите разобраться с чего начать.
    Есть ардуино уно и Ethernet shield
    Необходимо чтобы звук приходящий с аналогового микрофона, подключенного к аналоговому входу ардуино передать по сети на удаленный компьютер
    Есть ли какие то идеи или возможно пример
    Как преобразовать звук в сетевой пакет и передавать по сети??
     
  2. Tomasina

    Tomasina Сушитель лампочек Модератор

    а каким софтом компьютер будет преобразовывать "сетевой паке" обратно в звук?
     
  3. atlo

    atlo Нерд

    Пока не знаю, возможно на VB.net, что то буду писать, Изначально wiresharkoм посмотрю приходят пакеты, а дальше буду гуглить,
    Хотел узнать может у кого какой опыт есть или идей
     
  4. rkit

    rkit Гуру

    Вы представляете себе, как сделать простой усилитель сигнала на транзисторе?
     
  5. atlo

    atlo Нерд

  6. rkit

    rkit Гуру

    Вопрос был серьезный. Только не про то, умеете ли вы ткнуть по первой ссылке из гугла.
    Считать звук с микрофона на ардуино это весьма нетривиальная задача, требующая опыта как в программировании. так и в аналоговой обработке звука. И даже с этим приличного качества добиться не получится.
    Лучше опишите подробно задачу. а вам посоветуют, как лучше это реализовать.
     
  7. Radius

    Radius Гик

    Занимался передачей голоса по IP. Могу примерно рассказать как это делается. Звук оцифровывается с частотой 8 кГц. Затем выбираем голосовой кодек который позволяет сжать эти данные и существенно уменьшить скорость необходимую для передачи. Обычный PCM A-закон дает 64 кбит/сек, ADPCM - 32, 24 или 16 кБит/сек. Если хотите еще сильнее пожать то G726, G729. Дольше накапливаете данные 10 или 20 мсек и пакуете в UDP-пакет. Пакет передаете на компьютер, распаковываете, декодируете и с частотой 8 кГц выдаете на ЦАП. Это все упрощенно, а более детально почитайте про IP-телефонию.
     
  8. atlo

    atlo Нерд

    Есть небольшие опыт в электронике и побольше опыт в программирование и большой опыт по работе с ГУГЛОМ, ну и так же немного свободного времени(до наступления садово огородных работ :) )
    Если по существу, то есть ethernet shield b arduino uno,. необходимо к аналоговому входу арудуино подключить микрофон (в принципе это сделано и проверено взят за основу скетч написанный Дмитрием

    , голос на SD карту находящуюся на shielde W5100 пишется приемлемый) Необходимо через тот же shield w5100 передавать пакеты (buffer) по udp протоколу, на удаленный компьютер в сети.
    Как то так
     
  9. atlo

    atlo Нерд

    Спасибо за ответ, попробую порыть в сторону SIP
    Вопрос
    Я так понял, что звук сжимается с помощью микроконтроллера и только потом отправляется на удаленный ПК?? Хватит ли памяти у ардуино?
     
  10. Radius

    Radius Гик

    SIP - это протокол установления соединения в IP-телефонии. Для вас он не актуален. Пожать голос с помощью AVR-проблематично. Поэтому вы можете данные полученные с АЦП (10 бит) преобразовать в 1 байт (отбросить младшие разряды). Накопить 1250 отсчетов - это за 10 мс с частотой 8 кГц. Упаковать эти данные в UDP-пакет и передать через Ethernet. С другой стороны распаковать и с частотой 8 кГц выдать на ЦАП. Не уверен что это можно сделать с помощью ШИМ. Я на AVR использовал простейший R-2R ЦАП на одном из портов и получал приемлемые результаты.
     
  11. atlo

    atlo Нерд

    Спасибо,
    вопрос что значить накопить 1250 отсчетов - это имеется ввиду накопить данные в буфер (за 10 мс с частотой 8 кГц) и передать этот буфер через UDP протокол на удаленный комп?? Я правильно вас понял?
     
  12. Radius

    Radius Гик

    Да, правильно.
     
  13. atlo

    atlo Нерд

    Спасибо,
    буду пробовать
    Если, что я могу обратиться в личку? или лучше здесь?
     
  14. Radius

    Radius Гик

    Обращайтесь, чем смогу - помогу.
     
  15. atlo

    atlo Нерд

    Два вопроса
    Собрал код передает данные по udp на удаленный ПК взятые с аналогового входа к которому подключен микрофон
    Вопрос первый
    Выводится в serial порт следующие данные

    My IP address: 192.168.1.33Received packet of size 1
    From 192.168.1.176, port 3539
    Contents:
    41
    Received packet of size 1
    From 192.168.1.176, port 3539
    Contents:
    40

    На удаленном компе в консоле cmd(подключаюсь netcat) принимаются не числа как в сериал порту, а * ) и другие символы в зависимости от уровня звука принимаемого на микрофоне
    Как это изменить, что делаю не так, видимо тип данных не тот, тогда почему в сериал порт выводятся числа???
    И второй вопрос и лучше на примере
    Для того чтобы захватить звук я так понимаю нужно затолкать в передаваемый пакет диапазон(массив) передаваемых данных (а не одно значение как у меня) Подскажите как это реализовать, лучше еще раз повторюсь на примере
    Заранее благодарен!




    Код (C++):

    #include <SPI.h>         // требуется для Arduino версий 0018 и позже
    #include <Ethernet.h>
    #include <EthernetUdp.h>         // библиотека UDP library (из bjoern@cs.stanford.edu 12/30/2008)


    //KY-037 микрофонный модуль - аналоговый выход A0
    int microphonePin = A0; // выбор пина для входа от микрофона
    int microphoneValue = 0; // переменная для хранения значения от микрофона
    // IP-адрес :
    byte mac[] = {
      0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1, 33);
    unsigned int localPort = 8888;      // локальный порт, который будем прослушивать
    // буферы для получения и отправки данных
    char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // буфер, в котором будет храниться входящий пакет
    char  ReplyBuffer[] = "HELLO ";       // строка, которая будет отсылаться обратно
    // Создаем класс EthernetUDP, чтобы отправлять и получать пакеты через UDP:
    EthernetUDP Udp;
    void setup() {
       // Запускаем Ethernet и UDP:
      Ethernet.begin(mac,ip);
      Udp.begin(localPort);
      Serial.begin(9600);
      Serial.print("My IP address: ");
      Serial.print(Ethernet.localIP());
    }
    void loop() {
          // Если есть какие-либо доступные данные, считываем пакет:
      int packetSize = Udp.parsePacket();
      if(packetSize)
      {
        Serial.print("Received packet of size ");  //  "Получен пакет размером "
        Serial.println(packetSize);
        Serial.print("From ");  //  "От "
        IPAddress remote = Udp.remoteIP();
        for (int i =0; i < 4; i++)
        {
          Serial.print(remote[i], DEC);
          if (i < 3)
          {
            Serial.print(".");
          }
        }
        Serial.print(", port ");  //  ", порт "
        Serial.println(Udp.remotePort());
        // Считываем пакет в packetBufffer:
        Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
        Serial.println("Contents:");  //  "Содержимое:"
        Serial.println(packetBuffer);
        // Отсылаем ответ. Получатель – IP-адрес и порт,
        // от которых пришел полученный нами пакет:
        mic();
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write(microphoneValue);
        //Udp.write(ReplyBuffer);
        Udp.endPacket();
      }
      delay(10);
    }

    void mic(){
    microphoneValue = analogRead (microphonePin); //чтение значения с аналогового входа
        delay (microphoneValue);
        Serial.println (microphoneValue, DEC); // вывод значения в монитор порта
    String buff = String (microphoneValue, DEC);
    buff.toCharArray(ReplyBuffer, 1);
    //Serial.println (ReplyBuffer);
    Serial.println (microphoneValue);
    }
     
  16. rkit

    rkit Гуру

    Как раз числа и принимаются, а netcat их пытается декодировать в cp866.
    Пример работы с буфером есть в вашем же коде. Попробуйте разбирать примеры из интернета, а не просто копировать.
     
  17. atlo

    atlo Нерд

    В моем коде есть пример работы с буфером, но нет примера работы как захватить несколько значений за определенный промежуток времени или просто определенное количество.(Я поэтому и прошу совета как реализовать)
    И примеры которые я беру из интернета я обычно разбираю, может не настолько профессионально как Вы, но уж как умею.
    Вопрос к Вам как к Гуру, как netcat заставить выдавать те значения которые ему отправляет ардуино (сделать так чтобы он не пытался декодировать данные)
     
  18. rkit

    rkit Гуру

    Есть.


    Никак. Он не для этого. Пишите софт для звука. В нем сделаете вывод цифр, если нужен.
     
  19. atlo

    atlo Нерд

    Понял, спасибо
     
  20. atlo

    atlo Нерд

    Написал код вот так вроде данные передает, только через какое то время падает(перестает передавать данные, хотя устройство пингуется ) Вопрос это косяк программы или ардуино не вытягивает???
    Код (C++):

    #include <SPI.h>      
    #include <Ethernet.h>
    #include <EthernetUdp.h>


    // выход A0
    int microphonePin = A0; // выбор пина для входа от микрофона
    int microphoneValue = 0; // переменная для хранения значения от микрофона
    int i = 0; // для счетчика считывания аналоговых покозаний
    String str = "";

    byte mac[] = {
      0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1, 33);
    unsigned int localPort = 8;      // локальный порт, который будем прослушивать
    // буферы для получения и отправки данных
    char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // буфер, в котором будет храниться входящий пакет
    char  ReplyBuffer[100];       // строка, которая будет отсылаться обратно
    // Создаем экземпляр класса EthernetUDP, чтобы отправлять и получать пакеты через UDP:
    EthernetUDP Udp;
    void setup() {
       // Запускаем Ethernet и UDP:
      Ethernet.begin(mac,ip);
      Udp.begin(localPort);
     
      Serial.begin(9600);
      Serial.print("My IP address: ");
      Serial.print(Ethernet.localIP());
    }
    void loop() {
          // Если есть какие-либо доступные данные, считываем пакет:
      int packetSize = Udp.parsePacket();
      if(packetSize)
      {
     
        IPAddress remote = Udp.remoteIP();
       
        // Считываем пакет в packetBufffer:
        Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
       
        Serial.println("Contents:");  //  "Содержимое:"
       
       
        Serial.println(packetBuffer);
        //Serial.println (microphoneValue);
        Serial.println (ReplyBuffer);
        // Отсылаем ответ. Получатель – IP-адрес и порт,
        // от которых пришел полученный нами пакет:
       
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
         // отправляем значение
        Udp.write(ReplyBuffer);
        Udp.endPacket();
        str="";
      }
      delay(10);
      mic();
    }
    // записываем данные в буфер(массив)
    void mic(){
      str= str+String(analogRead(microphonePin), DEC)+"|";
      if(str.length()==100){
        str.toCharArray(ReplyBuffer,100);
      }
    }