LINUX.ORG.RU

Сообщения TsarcoV

 

Alsa программирование и сетевая передача данных

Здравствуйте, уважаемые форумчане. Пишу маленькую программу для сетевого голосового общения под Linux. Использую библиотеку alsa для звука. Собственно столкнулся с проблемой. Сломал всю голову уже. И так к сути... При передаче по сети через сокеты буффера с «голосом» получаю на выходе кучу помех,шуршаний, писка и так далее через которые слышен голос человека на другом конце. Шум и писк это пол беды. Я получаю на выходе грубо говоря несколько секунд такого безобразия, после чего звук обрывается, отрубаются уши на этот сеанс передачи( переполняется буффер как я думаю).При этом пакеты передаются и дальше и принимаются. Собственно проверял потери пакетов, они отсутствуют. Похожей писк идет когда идет заполнение допустим 0лями буффера. На клиенте ( исходном компьютере ) голос идет без помех, без писков, без потерь( с микрофона выдаю сразу в колонки(уши, гарнитуру) звук). Отсюда вопрос с одной стороны к людям разбирающемся в alsa, из за чего может вырубаться звук. С другой стороны вопрос почему правильные изначально данные при передаче обрастают писками и шумами? Вот функция передачи голоса

( читать дальше... )

А вот кусок кода сервера

( читать дальше... )

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

 , , ,

TsarcoV
()

Alsa программирование

Здравствуйте, работаю на Linux в 1 раз, поэтому наверно вопрос будет немного простой, но для меня пока что, сложный. Занят проектом под Linux, вкратце если то нужна говорилка между компами. Написать желательно под alsa. Вроде как то разобрался в чем то. Примеры различные, запустил. На данный момент добился того что бы 1 программа записывала в файл фрагмент звука. А 2ой программой можно было этот фрагмент прочитать. Проблема в том что я собираю файл, а потом через консоль находясь в директории с программой набирай ./programmRecord > NameFile.mp3 ( на запись ) и ./ProgrammPlay < NameFile.mp3 ( на чтение ). Собственно вопрос: 1. Как можно сделать ввод файла в самой программе? Чтобы убрать участие консоли. 2. Не совсем понятно где именно идет передача в сам файл.( Пример брал из книжки, но так корректно и не понял можно ли обойтись без файла. Что бы сохранял значение в промежуточной переменной. Проблема только в работе со звуком. По факту не понятно как в буффер передать данные с микрофона и как их подать на наушники(колонки). Остальное все я представляю как делать.

Вот код примера с которым работаю.

/*

This example reads standard from input and writes
to the default PCM device for 5 seconds of data.

*/

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API

#include <alsa/asoundlib.h>

int main() {
  long loops;
  int rc;
  int size;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *params;
  unsigned int val;
  int dir;
  snd_pcm_uframes_t frames;
  char *buffer;

  /* Open PCM device for playback. */
  rc = snd_pcm_open(&handle, "hw:0,0",
                    SND_PCM_STREAM_PLAYBACK, 0);
  if (rc < 0) {
    fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc));
    exit(1);
  }

  /* Allocate a hardware parameters object. */
  snd_pcm_hw_params_alloca(&params);

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle, params);

  /* Set the desired hardware parameters. */

  /* Interleaved mode */
  snd_pcm_hw_params_set_access(handle, params,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

  /* Signed 16-bit little-endian format */
  snd_pcm_hw_params_set_format(handle, params,
                              SND_PCM_FORMAT_S16_LE);

  /* Two channels (stereo) */
  snd_pcm_hw_params_set_channels(handle, params, 2);

  /* 44100 bits/second sampling rate (CD quality) */
  val = 44100;
  snd_pcm_hw_params_set_rate_near(handle, params,
                                  &val, &dir);

  /* Set period size to 32 frames. */
  frames = 32;
  snd_pcm_hw_params_set_period_size_near(handle,
                              params, &frames, &dir);

  /* Write the parameters to the driver */
  rc = snd_pcm_hw_params(handle, params);
  if (rc < 0) {
    fprintf(stderr,
            "unable to set hw parameters: %s\n",
            snd_strerror(rc));
    exit(1);
  }

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(params, &frames,
                                    &dir);
  size = frames * 4; /* 2 bytes/sample, 2 channels */
  buffer = (char *) malloc(size);

  /* We want to loop for 5 seconds */
  snd_pcm_hw_params_get_period_time(params,
                                    &val, &dir);
  /* 5 seconds in microseconds divided by
   * period time */
  loops = 5000000 / val;

  while (loops > 0) {
    loops--;
    rc = read(0, buffer, size);
    if (rc == 0) {
      fprintf(stderr, "end of file on input\n");
      break;
    } else if (rc != size) {
      fprintf(stderr,
              "short read: read %d bytes\n", rc);
    }
    rc = snd_pcm_writei(handle, buffer, frames);
    if (rc == -EPIPE) {
      /* EPIPE means underrun */
      fprintf(stderr, "underrun occurred\n");
      snd_pcm_prepare(handle);
    } else if (rc < 0) {
      fprintf(stderr,
              "error from writei: %s\n",
              snd_strerror(rc));
    }  else if (rc != (int)frames) {
      fprintf(stderr,
              "short write, write %d frames\n", rc);
    }
  }

  snd_pcm_drain(handle);
  snd_pcm_close(handle);
  free(buffer);

  return 0;
}


Дополнение 1 : Как всегда после написания, голова начала работать и вроде понял что должно быть что то вроде

 

fd = open("file_rec", O_RDWR);
if(!fd)
printf("file didn't open\n");

  while (loops > 0) {
    loops--;

    b = snd_pcm_readi(fd, buffer, frames);
    write(fd, buffer, size);

  }

Но выдается при запуски ошибка сегментации. Пока что не понял из за чего.

 

TsarcoV
()

RSS подписка на новые темы