LINUX.ORG.RU

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

 , , ,


0

1

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

void speak()
{
    long loops;
    int sock; 	
    int rc;
     int ch;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer;
    int  fd,b;
    char msg;
        rc = snd_pcm_open(&handle, "hw:0,2,1",
                    SND_PCM_STREAM_CAPTURE, 0);    
        snd_pcm_hw_params_alloca(&params);
        snd_pcm_hw_params_any(handle, params);
        snd_pcm_hw_params_set_access(handle, params,
                      SND_PCM_ACCESS_RW_INTERLEAVED);
        snd_pcm_hw_params_set_format(handle, params,
                              SND_PCM_FORMAT_S16_LE);

        snd_pcm_hw_params_set_channels(handle, params, 2);
        val = 44100;
        snd_pcm_hw_params_set_rate_near(handle, params,
                                  &val, &dir);     
        frames = 32;
        snd_pcm_hw_params_set_period_size_near(handle,
                              params, &frames, &dir);
        rc = snd_pcm_hw_params(handle, params);      
        snd_pcm_hw_params_get_period_size(params,
                                      &frames, &dir);
        size = frames * 4; 
        buffer = (char *) malloc(size);
        snd_pcm_hw_params_get_period_time(params,
                                         &val, &dir);
        changemode(1);
        int i;
        sock = connectsock("127.0.0.1", "1231", "tcp");
		if(sock < 0)	//проверяем дескриптор сокета
			printf("nety connecta");
			else
			{printf("connect esti");
        while(loops>0)
            {
                                    rc = snd_pcm_readi(handle, buffer, frames);
                                    send(sock,buffer, frames, 0);
            }
			}



    changemode(0);
    close(fd);
    close(sock);
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);

}

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

void speakOut()
{

    int msock, csock;				
	struct sockaddr_in  remaddr;			
	unsigned int remaddrs = sizeof(remaddr);	
	char msg[32];					
	int buff_out;



long loops;
  int rc,wc;
  int size;
  snd_pcm_t *handle,*handle_Out;
  snd_pcm_hw_params_t *params,*params_Out;
  unsigned int val;
  int dir;
  snd_pcm_uframes_t frames;
  char *buffer,*buffer_Out;
  int  fd,b;
  int Mode=0,Menu;
  wc = snd_pcm_open(&handle_Out, "hw:0,0",
                    SND_PCM_STREAM_PLAYBACK, 0);


  snd_pcm_hw_params_alloca(&params_Out);
  snd_pcm_hw_params_any(handle_Out, params_Out);
 snd_pcm_hw_params_set_access(handle_Out, params_Out,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

snd_pcm_hw_params_set_format(handle_Out, params_Out,
                              SND_PCM_FORMAT_S16_LE);

 snd_pcm_hw_params_set_channels(handle_Out, params_Out, 2);

  val = 44100;


snd_pcm_hw_params_set_rate_near(handle_Out, params_Out,
                                  &val, &dir);
  frames = 32;

 snd_pcm_hw_params_set_period_size_near(handle_Out,
                              params_Out, &frames, &dir);

  wc = snd_pcm_hw_params(handle_Out, params_Out);

snd_pcm_hw_params_get_period_size(params_Out,
                                      &frames, &dir);
  size = frames * 4; 
  buffer = (char *) malloc(size);

  
snd_pcm_hw_params_get_period_time(params_Out,
                                         &val, &dir);

	msock = sock("1231", "tcp", 5);
	if(msock < 0)			
		return -1;		

        csock = accept(msock, (struct sockaddr*) &remaddr, &remaddrs);	
		if(csock < 0)		
			printf("Ошибка принятия подключения: \n");
		else			
	 		{
	while(1)	
	                   {
	    

				read(csock, &msg, sizeof(msg));
                buffer_Out=msg;
                wc= snd_pcm_writei (handle_Out, msg, frames);
                memset(&msg, 0, sizeof(msg));

                           }
                        }


close(fd);
  snd_pcm_drain(handle_Out);
  snd_pcm_close(handle_Out);
  free(buffer_Out);
  close(csock);
close(msock);	

			
}

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



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

Витую пару надо использовать экранированную. Если серьезно, то для начала неплохо бы начать проверять, что возвращают send, recv, snd_pcm_readi, snd_pcm_writei. В первом листинге send должен принимать в качестве длины frames * 4, не? И что за странная переменная msg во втором листинге?

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

char msg[32];

думаю в этом дело. нужно char msg[frames * 4]

waker ★★★★★
()

Где проверка ошибок? Где очередь? Где восстановление после ошибки? Ничего нет, ничего и не работает.

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