LINUX.ORG.RU

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

 


0

1

Здравствуйте, работаю на 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);

  }

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



Последнее исправление: cetjs2 (всего исправлений: 4)

в 1 раз

Извиняюсь за грамманацизм, но. 1. К порядковым числам ставится окончание. 1-ый 2. Числа из одной цифры лучше всё-же писать словами.

anonymous
()

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

Ну, очевидно, что если !fd, то надо что-нибудь типа return вставить. А то ты пытаешься писать в несуществующий дескриптор.

Ну и размеры frames и buffer надо аккуратно посмотреть.

P.S.: В программировании alsa я вообще не разбираюсь, так что это весьма обобщенные замечания...

solovey ★★
()
Ответ на: комментарий от anonymous

Что за дескриминация анона, ему уже перед собой извиниться нельзя? Вот увидел человек ошибку (я тоже долго соображал, что за «1»), знает, что оффтоп, стыдно, но исправлять то надо. Конечно на ТС и окружающих всем насрать, поэтому и приходится извиняться перед собой культурным.

Я тоже извиняюсь.

staseg ★★★★★
()
Ответ на: комментарий от staseg

дескриминация

агрррррр!!!!

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

Harald ★★★★★
()
Ответ на: комментарий от Harald

агрррррр!!!!

Еще раз извиняюсь!

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

+

staseg ★★★★★
()

с одной стороны arecord | nc, с другой - nc -l | aplay
правильно Harald говорит ;)

aol ★★★★★
()

Рекомендую portaudio - платформонезависимая и простая в изучении библиотека для подобных задач.

float
()
Ответ на: комментарий от staseg

я гляжу в этом треде все извиняются, тоже воспользуюсь ситуацией

Извиняюсь!

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

++, netcat наше фсио

lazyklimm ★★★★★
()
Ответ на: комментарий от anonymous

в таком случае, «прощаюсь» - это «прощаю себя». что за задорновщина.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.