Пример #1
0
/**
 * \brief Wait for a PCM to become ready
 * \param pcm ordinary PCM handle
 * \param timeout maximum time in milliseconds to wait
 * \return a positive value on success otherwise a negative error code
 * \retval 0 timeout occurred
 * \retval 1 PCM stream is ready for I/O
 */
int sndo_pcm_wait(sndo_pcm_t *pcm, int timeout)
{
        struct pollfd pfd[2];
        unsigned short p_revents, c_revents;
        int err;
        err = snd_pcm_poll_descriptors(pcm->playback, &pfd[0], 1);
        assert(err == 1);
        err = snd_pcm_poll_descriptors(pcm->capture, &pfd[1], 1);
        assert(err == 1);
        err = poll(pfd, 2, timeout);
        if (err < 0)
                return -errno;
	if (err == 0)
		return 0;
	do {
	        err = snd_pcm_poll_descriptors_revents(pcm->playback, &pfd[0], 1, &p_revents);
		if (err < 0)
			return err;
		if (p_revents & (POLLERR | POLLNVAL))
			return -EIO;
		err = snd_pcm_poll_descriptors_revents(pcm->capture, &pfd[1], 1, &c_revents);
		if (err < 0)
			return err;
		if (c_revents & (POLLERR | POLLNVAL))
			return -EIO;
		if ((p_revents & POLLOUT) && (c_revents & POLLIN))
			return 1;
		err = poll(&pfd[(p_revents & POLLOUT) ? 1 : 0], 1, 1);
		if (err < 0)
			return err;
	} while (1);
}
Пример #2
0
void
alsa_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
	int err;
	struct pollfd *f;

	if (out_handle && !rdpsnd_queue_empty())
	{
		num_fds_out = snd_pcm_poll_descriptors_count(out_handle);

		if (num_fds_out > sizeof(pfds_out) / sizeof(*pfds_out))
			return;

		err = snd_pcm_poll_descriptors(out_handle, pfds_out, num_fds_out);
		if (err < 0)
			return;

		for (f = pfds_out; f < &pfds_out[num_fds_out]; f++)
		{
			if (f->events & POLLIN)
				FD_SET(f->fd, rfds);
			if (f->events & POLLOUT)
				FD_SET(f->fd, wfds);
			if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
				*n = f->fd;
		}
	}

	if (in_handle)
	{
		num_fds_in = snd_pcm_poll_descriptors_count(in_handle);

		if (num_fds_in > sizeof(pfds_in) / sizeof(*pfds_in))
			return;

		err = snd_pcm_poll_descriptors(in_handle, pfds_in, num_fds_in);
		if (err < 0)
			return;

		for (f = pfds_in; f < &pfds_in[num_fds_in]; f++)
		{
			if (f->events & POLLIN)
				FD_SET(f->fd, rfds);
			if (f->events & POLLOUT)
				FD_SET(f->fd, wfds);
			if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
				*n = f->fd;
		}
	}
}
Пример #3
0
static char poll_setup (void)
{
    if (pipe (poll_pipe))
    {
        ERROR ("Failed to create pipe: %s.\n", strerror (errno));
        return 0;
    }

    if (fcntl (poll_pipe[0], F_SETFL, O_NONBLOCK))
    {
        ERROR ("Failed to set O_NONBLOCK on pipe: %s.\n", strerror (errno));
        close (poll_pipe[0]);
        close (poll_pipe[1]);
        return 0;
    }

    poll_count = 1 + snd_pcm_poll_descriptors_count (alsa_handle);
    poll_handles = g_new (struct pollfd, poll_count);
    poll_handles[0].fd = poll_pipe[0];
    poll_handles[0].events = POLLIN;
    poll_count = 1 + snd_pcm_poll_descriptors (alsa_handle, poll_handles + 1,
     poll_count - 1);

    return 1;
}
Пример #4
0
int audioStreamer_ALSA::Read(char *buf, int len) // returns 0 if blocked, < 0 if error, > 0 if data
{
	int ret;
	if (m_sleep >= 0)
	{
		struct pollfd pfds[32];
		int cnt=snd_pcm_poll_descriptors(pcm_handle,pfds,32);
		if (cnt>0) poll(pfds,cnt,m_sleep);
	}

	ret=snd_pcm_readi(pcm_handle, buf, len/(m_nch*(m_bps/8)));

	if (ret < 0) 
	{
		if (ret != -EAGAIN) { snd_pcm_prepare(pcm_handle);  }
		return 0;
	}
#if 0
	snd_pcm_sframes_t del=0;
	if (!snd_pcm_delay(pcm_handle,&del) && del > m_bufsize/2 /* JF>used to be /1 */)
	{
		audiostream_onover();
		for (;;) if (snd_pcm_readi(pcm_handle, buf, len/(m_nch*(m_bps/8)))<0) break;
		// we have too many samples, eat some
	}
#endif

	return ret*m_nch*(m_bps/8);
}
Пример #5
0
/* Oversimplistic fileno() implementation assuming there's only one file-
 * descriptor involved. Should be the case anyway */
int audio_fileno(void)
{
	struct pollfd pfd;

	snd_pcm_poll_descriptors(playback_handle, &pfd, 1);

	return pfd.fd;
}
Пример #6
0
AudioAlsa::AudioAlsa( bool & _success_ful, Mixer*  _mixer ) :
	AudioDevice( tLimit<ch_cnt_t>(
		ConfigManager::inst()->value( "audioalsa", "channels" ).toInt(),
					DEFAULT_CHANNELS, SURROUND_CHANNELS ),
								_mixer ),
	m_handle( NULL ),
	m_hwParams( NULL ),
	m_swParams( NULL ),
	m_convertEndian( false )
{
	_success_ful = false;

	int err;

	if( ( err = snd_pcm_open( &m_handle,
					probeDevice().toLatin1().constData(),
						SND_PCM_STREAM_PLAYBACK,
						0 ) ) < 0 )
	{
		printf( "Playback open error: %s\n", snd_strerror( err ) );
		return;
	}

	snd_pcm_hw_params_malloc( &m_hwParams );
	snd_pcm_sw_params_malloc( &m_swParams );

	if( ( err = setHWParams( channels(),
					SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
	{
		printf( "Setting of hwparams failed: %s\n",
							snd_strerror( err ) );
		return;
	}
	if( ( err = setSWParams() ) < 0 )
	{
		printf( "Setting of swparams failed: %s\n",
							snd_strerror( err ) );
		return;
	}

	// set FD_CLOEXEC flag for all file descriptors so forked processes
	// do not inherit them
	struct pollfd * ufds;
	int count = snd_pcm_poll_descriptors_count( m_handle );
	ufds = new pollfd[count];
	snd_pcm_poll_descriptors( m_handle, ufds, count );
	for( int i = 0; i < qMax( 3, count ); ++i )
	{
		const int fd = ( i >= count ) ? ufds[0].fd+i : ufds[i].fd;
		int oldflags = fcntl( fd, F_GETFD, 0 );
		if( oldflags < 0 )
			continue;
		oldflags |= FD_CLOEXEC;
		fcntl( fd, F_SETFD, oldflags );
	}
	delete[] ufds;
	_success_ful = true;
}
Пример #7
0
static void
alsa_write( char *buf, int size ) 
{
	struct pollfd pfd;

	snd_pcm_poll_descriptors( alsa.pcm, &pfd, 1 );
	poll( &pfd, 1, -1 );

	snd_pcm_writei( alsa.pcm, buf, size/alsa.bpf );
}
Пример #8
0
/**
 * \brief get poll descriptors
 * \param pcm ordinary pcm handle
 * \param pfds array of poll descriptors
 * \param space space in the poll descriptor array
 * \return count of filled descriptors
 */     
int sndo_pcm_poll_descriptors(sndo_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
{
	int playback, err, res = 0;

	playback = snd_pcm_poll_descriptors_count(pcm->playback);
	if (playback < 0)
		return playback;
	err = snd_pcm_poll_descriptors(pcm->playback, pfds, (unsigned)playback < space ? (unsigned)playback : space);
	if (err < 0)
		return err;
	res += err;
	if ((unsigned)res < space) {
		err = snd_pcm_poll_descriptors(pcm->capture, pfds + res, space - res);
		if (err < 0)
			return err;
		res += err;
	}
	return res;
}
Пример #9
0
/* FIXME: proper lock? */
static void*
alsa_loop(void* arg) {
	int npfds = snd_pcm_poll_descriptors_count(alsa_pcm);
	struct pollfd* pfds;
	unsigned short* revents;

	if(npfds <= 0)
		goto _error;

	//printf("Starting alsa_loop thread...\n");

	pfds = alloca(sizeof(*pfds) * npfds);
	revents = alloca(sizeof(*revents) * npfds);

	while(going && alsa_pcm) {
		if(get_thread_buffer_filled() > prebuffer_size)
			prebuffer = false;

		if(!prebuffer && get_thread_buffer_filled() > hw_period_size_in) {
			snd_pcm_poll_descriptors(alsa_pcm, pfds, npfds);

			if(poll(pfds, npfds, 10) > 0) {
				/*
				 * need to check revents.  poll() with
				 * dmix returns a postive value even
				 * if no data is available
				 */
				int i;
				snd_pcm_poll_descriptors_revents(alsa_pcm, pfds,
				                                 npfds, revents);

				for(i = 0; i < npfds; i++)
					if(revents[i] & POLLOUT) {
						alsa_write_out_thread_data();
						break;
					}
			}
		} else
			usleep(10000);

		if(flush_request != -1) {
			alsa_do_flush(flush_request);
			flush_request = -1;
			prebuffer = true;
		}
	}

_error:
	alsa_close_pcm();
	free(thread_buffer);
	thread_buffer = NULL;
	pthread_exit(NULL);
}
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    struct pollfd *pfds;

    if (argc < 6) {
        fprintf(stderr, "LinzerSchnitteMIDI <hw:0,0,1> <attack> <decay> <sustain> <release>\n"); 
        exit(1);
    }

    attack = atof(argv[2]);
    decay = atof(argv[3]);
    sustain = atof(argv[4]);
    release = atof(argv[5]);
/*    polyphony = atoi(argv[6]);
    buffersize = atoi(argv[7]);
    outputvolume = atoi(argv[8]);
    firstnotefreq = atoi(argv[9]);
    freqchannelwidth = atoi(argv[10]);
*/
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(argv[1]);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    connect2MidiThroughPort(seq_handle);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
        if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {
                if (pfds[l1].revents > 0) {
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun ! increase buffer \n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
Пример #11
0
static void Poll (snd_pcm_t *pcm, int canc)
{
    int n = snd_pcm_poll_descriptors_count (pcm);
    struct pollfd ufd[n];
    unsigned short revents;

    snd_pcm_poll_descriptors (pcm, ufd, n);
    do
    {
        vlc_restorecancel (canc);
        while (poll (ufd, n, -1) == -1);
        canc = vlc_savecancel ();
        snd_pcm_poll_descriptors_revents (pcm, ufd, n, &revents);
    }
    while (!revents);
}
Пример #12
0
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    struct pollfd *pfds;
    
    if (argc < 10) {
        fprintf(stderr, "miniFMsynth <device> <FM> <harmonic> <subharmonic> <transpose> <a> <d> <s> <r>\n"); 
        exit(1);
    }
    modulation = atof(argv[2]);
    harmonic = atoi(argv[3]);
    subharmonic = atoi(argv[4]);
    transpose = atoi(argv[5]);
    attack = atof(argv[6]);
    decay = atof(argv[7]);
    sustain = atof(argv[8]);
    release = atof(argv[9]);
    pitch = 0;
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(argv[1]);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
        if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {    
                if (pfds[l1].revents > 0) { 
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun !\n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }        
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
Пример #13
0
void alsa_poll_descriptors(alsa_dev_t *alsa_dev, struct pollfd **pfds, int *count)
{
    int32_t rc;

    *count = snd_pcm_poll_descriptors_count(alsa_dev->snd_pcm);
    if (*count <= 0)
    {
        syslog(LOG_ERR, "Invalid poll descriptors count");
        exit(EXIT_FAILURE);
    }

    *pfds = malloc(sizeof(struct pollfd) * (*count));

    memset(*pfds, 0, sizeof(struct pollfd) * (*count));

    rc = snd_pcm_poll_descriptors(alsa_dev->snd_pcm, *pfds, *count);
    if (rc < 0)
    {
        syslog(LOG_ERR, "Unable to obtain poll descriptors for capture: %s",
               snd_strerror(rc));
        exit(EXIT_FAILURE);
    }
}
Пример #14
0
static ssize_t pcm_pollfds(struct alsa_pcm *alsa, struct pollfd *pe,
			   size_t z)
{
    int r, count;

    count = snd_pcm_poll_descriptors_count(alsa->pcm);
    if (count > z)
        return -1;

    if (count == 0)
        alsa->pe = NULL;
    else {
        r = snd_pcm_poll_descriptors(alsa->pcm, pe, count);
        if (r < 0) {
            alsa_error("poll_descriptors", r);
            return -1;
        }
        alsa->pe = pe;
    }

    alsa->pe_count = count;
    return count;
}
Пример #15
0
void* startSnd(void *arg){
   sndbuf = (short *) malloc (2 * sizeof (short) * BUFSAMPS); //each sample is 2 chans, 2 byte shorts
   if(!sndbuf){free(snddat);return NULL;}
   pcm_handle = open_pcm("hw:0,0");
   if(!pcm_handle){free(sndbuf);free(snddat);return NULL;}
   memset(sndbuf, 0, 2 * sizeof (short) * BUFSAMPS);
   int nfds = snd_pcm_poll_descriptors_count (pcm_handle);
   struct pollfd *pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * nfds);
   snd_pcm_poll_descriptors(pcm_handle, pfds, nfds);
   while(!bQuit){
      if (poll (pfds, nfds, 1000) > 0) {
         int i;
         for (i = 0; i < nfds; i++) {    
            if (pfds[i].revents > 0) { 
               if (playback_callback(BUFSAMPS) < BUFSAMPS) snd_pcm_prepare(pcm_handle);
            }
         } 
      }
   }
   snd_pcm_close(pcm_handle);
   free(sndbuf);free(snddat);
   return NULL;
}
int main (int argc, char *argv[]) {

    int nfds, seq_nfds, l1;
    //int key;
    //key=0;
    char *hwdevice;
    struct pollfd *pfds;
/*
    if (argc < 2) {
        fprintf(stderr, "LinzerSchnitteMIDI <hw:0,0,1> <attack> <decay> <sustain> <release>\n"); 
        exit(1);
    }
*/
    initscr();				  /* start the curses setup */
    atexit(do_endwin);
    keypad(stdscr, TRUE);
    noecho();
    scrollok(stdscr, TRUE);
    printw("Welcome to LinzerSchnitte\n");
    refresh();
    start_color();	
    init_pair(1, COLOR_RED, COLOR_BLACK); /* end the curses setup */

/* Set default */    
    hwdevice = "hw:0,0,1";
    attack = 0.001;
    decay = 0.001;
    sustain = 1;
    release = 0.001;	
    
    if (argc > 1) {
    	hwdevice = argv[1];
    }

/*    attack = atof(argv[2]);
    decay = atof(argv[3]);
    sustain = atof(argv[4]);
    release = atof(argv[5]);
*/  
    buf = (short *) malloc (2 * sizeof (short) * BUFSIZE);
    playback_handle = open_pcm(hwdevice);
    seq_handle = open_seq();
    seq_nfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN);
    nfds = snd_pcm_poll_descriptors_count (playback_handle);
    pfds = (struct pollfd *)alloca(sizeof(struct pollfd) * (seq_nfds + nfds));
    snd_seq_poll_descriptors(seq_handle, pfds, seq_nfds, POLLIN);
    snd_pcm_poll_descriptors (playback_handle, pfds+seq_nfds, nfds);
    connect2MidiThroughPort(seq_handle);
    for (l1 = 0; l1 < POLY; note_active[l1++] = 0);
    while (1) {
	if (poll (pfds, seq_nfds + nfds, 1000) > 0) {
            for (l1 = 0; l1 < seq_nfds; l1++) {
               if (pfds[l1].revents > 0) midi_callback();
            }
            for (l1 = seq_nfds; l1 < seq_nfds + nfds; l1++) {
                if (pfds[l1].revents > 0) {
                    if (playback_callback(BUFSIZE) < BUFSIZE) {
                        fprintf (stderr, "xrun ! increase buffer \n");
                        snd_pcm_prepare(playback_handle);
                    }
                }
            }
        }
    }
    snd_pcm_close (playback_handle);
    snd_seq_close (seq_handle);
    free(buf);
    return (0);
}
Пример #17
0
/* alsa_init:
 *  ALSA init routine.
 */
static int alsa_init(int input, int voices)
{
   int ret = 0;
   char tmp1[128], tmp2[128];
   int format = 0;
   unsigned int numfrags = 0;
   snd_pcm_uframes_t fragsize;

   if (input) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
      return -1;
   }

   ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0));

   alsa_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_device", tmp2),
				   alsa_device);

   alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_mixer_device", tmp2),
				   alsa_mixer_device);

   fragsize = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_fragsize", tmp2), 0);

   numfrags = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_numfrags", tmp2),
			     ALSA_DEFAULT_NUMFRAGS);

   ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
   if (ret < 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
      return -1;
   }

   snd_mixer_open(&alsa_mixer, 0);

   if (alsa_mixer
       && snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0
       && snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0
       && snd_mixer_load(alsa_mixer) >= 0) {
      const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1),
							   uconvert_ascii("alsa_mixer_elem", tmp2),
							   "PCM");

      alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer);

      while (alsa_mixer_elem) {
	 const char *name = snd_mixer_selem_get_name(alsa_mixer_elem);

	 if (strcasecmp(name, alsa_mixer_elem_name) == 0) {
	    snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max);
	    alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255;
	    break;
	 }

	 alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem);
      }
   }

   /* Set format variables. */
   alsa_bits = (_sound_bits == 8) ? 8 : 16;
   alsa_stereo = (_sound_stereo) ? 1 : 0;
   alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100;
   alsa_signed = 0;

   format = ((alsa_bits == 16) ? SND_PCM_FORMAT_U16_NE : SND_PCM_FORMAT_U8);

   switch (format) {

      case SND_PCM_FORMAT_U8:
	 alsa_bits = 8;
	 break;

      case SND_PCM_FORMAT_U16_NE:
	 if (sizeof(short) != 2) {
	    ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	    goto Error;
	 }
	 break;

      default:
	 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	 goto Error;
   }

   alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1);

   if (fragsize == 0) {
      unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags;
      fragsize = 1;
      while (fragsize < size)
	 fragsize <<= 1;
   }

   snd_pcm_hw_params_malloc(&hwparams);
   snd_pcm_sw_params_malloc(&swparams);

   ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams));
   ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED));
   ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format));
   ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1));

   ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL)); 

   ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams));

   ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL));

   TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments);

   ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams));
   ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_xfer_align(pcm_handle, swparams, 1));
   ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams));

   /* Allocate mixing buffer. */
   alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size);
   if (!alsa_bufdata) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
      goto Error;
   }

   /* Initialise mixer. */
   digi_alsa.voices = voices;

   if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate,
		   alsa_stereo, ((alsa_bits == 16) ? 1 : 0),
		   &digi_alsa.voices) != 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
      goto Error;
   }

   snd_pcm_prepare(pcm_handle);
   pdc = snd_pcm_poll_descriptors_count (pcm_handle);
   if (pdc <= 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count"));
      goto Error;
   }

   ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc);
   if (ufds == NULL) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors"));
      goto Error;
   }
   ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc));

   poll_next = 0;

   _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);

   /* Add audio interrupt. */
   _unix_bg_man->register_func(alsa_update);

   uszprintf(alsa_desc, sizeof(alsa_desc),
	     get_config_text
	     ("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"),
	     alsa_device, alsa_bits,
	     uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1),
	     alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2));

   digi_driver->desc = alsa_desc;
   return 0;

 Error:
   if (pcm_handle) {
      snd_pcm_close(pcm_handle);
      pcm_handle = NULL;
   }

   return -1;
}
Пример #18
0
bool
ALSAPCMPlayer::Start(PCMDataSource &_source)
{
  const unsigned new_sample_rate = _source.GetSampleRate();

  if ((nullptr != source) &&
      alsa_handle &&
      (source->GetSampleRate() == new_sample_rate)) {
    /* just change the source / resume playback */
    bool success = false;
    DispatchWait(io_service, [this, &_source, &success]() {
      bool recovered_from_underrun = false;

      switch (snd_pcm_state(alsa_handle.get())) {
      case SND_PCM_STATE_XRUN:
        if (0 != snd_pcm_prepare(alsa_handle.get()))
          return;
        else {
          recovered_from_underrun = true;
          success = true;
        }
        break;

      case SND_PCM_STATE_RUNNING:
        success = true;
        break;

      default:
        return;
      }

      if (success) {
        source = &_source;

        if (recovered_from_underrun) {
          const size_t n = buffer_size / channels;
          const size_t n_read = FillPCMBuffer(buffer.get(), n);
          if (!WriteFrames(n_read)) {
            success = false;
            return;
          }
        }

        if (success)
          StartEventHandling();
      }
    });
    if (success)
      return true;
  }

  Stop();

  assert(!alsa_handle);

  AlsaHandleUniquePtr new_alsa_handle = MakeAlsaHandleUniquePtr();
  {
    const char *alsa_device = ALSAEnv::GetALSADeviceName();

    snd_pcm_t *raw_alsa_handle;
    int alsa_error = snd_pcm_open(&raw_alsa_handle, alsa_device,
                                  SND_PCM_STREAM_PLAYBACK, 0);
    if (alsa_error < 0) {
      LogFormat("snd_pcm_open(0x%p, \"%s\", SND_PCM_STREAM_PLAYBACK, 0) "
                    "failed: %s",
                &alsa_handle, alsa_device, snd_strerror(alsa_error));
      return false;
    }
    new_alsa_handle = MakeAlsaHandleUniquePtr(raw_alsa_handle);
    assert(new_alsa_handle);
  }

  unsigned latency = ALSAEnv::GetALSALatency();

  channels = 1;
  bool big_endian_source = _source.IsBigEndian();
  if (!SetParameters(*new_alsa_handle, new_sample_rate, big_endian_source,
                     latency, channels))
    return false;

  snd_pcm_sframes_t n_available = snd_pcm_avail(new_alsa_handle.get());
  if (n_available <= 0) {
    LogFormat("snd_pcm_avail(0x%p) failed: %ld - %s",
              new_alsa_handle.get(),
              static_cast<long>(n_available),
              snd_strerror(static_cast<int>(n_available)));
    return false;
  }

  buffer_size = static_cast<snd_pcm_uframes_t>(n_available * channels);
  buffer = std::unique_ptr<int16_t[]>(new int16_t[buffer_size]);

  /* Why does Boost.Asio make it so hard to register a set of of standard
     poll() descriptors (struct pollfd)? */
  int poll_fds_count = snd_pcm_poll_descriptors_count(new_alsa_handle.get());
  if (poll_fds_count < 1) {
    LogFormat("snd_pcm_poll_descriptors_count(0x%p) returned %d",
              new_alsa_handle.get(),
              poll_fds_count);
    return false;
  }

  std::unique_ptr<struct pollfd[]> poll_fds(
      new struct pollfd[poll_fds_count]);
  BOOST_VERIFY(
      poll_fds_count ==
          snd_pcm_poll_descriptors(new_alsa_handle.get(),
                                   poll_fds.get(),
                                   static_cast<unsigned>(poll_fds_count)));

  for (int i = 0; i < poll_fds_count; ++i) {
    if ((poll_fds[i].events & POLLIN) || (poll_fds[i].events & POLLPRI)) {
      read_poll_descs.emplace_back(
          boost::asio::posix::stream_descriptor(io_service, poll_fds[i].fd));
    }
    if (poll_fds[i].events & POLLOUT) {
      write_poll_descs.emplace_back(
          boost::asio::posix::stream_descriptor(io_service, poll_fds[i].fd));
    }
  }

  source = &_source;
  size_t n_read = FillPCMBuffer(buffer.get(), static_cast<size_t>(n_available));

  if (0 == n_read) {
    LogFormat("ALSA PCMPlayer started with data source which "
                  "does not deliver any data");
    return false;
  }

  if (!WriteFrames(*new_alsa_handle, buffer.get(),
                   static_cast<size_t>(n_available), false))
    return false;

  alsa_handle = std::move(new_alsa_handle);

  StartEventHandling();

  return true;
}
Пример #19
0
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period)
{
   int dir;
   int err;
   snd_pcm_hw_params_t *hw_params;
   snd_pcm_sw_params_t *sw_params;
   snd_pcm_uframes_t period_size = period;
   snd_pcm_uframes_t buffer_size = PERIODS*period;
   static snd_output_t *jcd_out;
   AlsaDevice *dev = malloc(sizeof(*dev));
   if (!dev)
      return NULL;
   dev->device_name = malloc(1+strlen(device_name));
   if (!dev->device_name)
   {
      free(dev);
      return NULL;
   }
   strcpy(dev->device_name, device_name);
   dev->channels = channels;
   dev->period = period;
   err = snd_output_stdio_attach(&jcd_out, stdout, 0);
   
   if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
      fprintf (stderr, "cannot open audio device %s (%s)\n",
               dev->device_name,
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
      fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_any (dev->capture_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_access (dev->capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
      fprintf (stderr, "cannot set access type (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_format (dev->capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
      fprintf (stderr, "cannot set sample format (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_rate_near (dev->capture_handle, hw_params, &rate, 0)) < 0) {
      fprintf (stderr, "cannot set sample rate (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*fprintf (stderr, "rate = %d\n", rate);*/

   if ((err = snd_pcm_hw_params_set_channels (dev->capture_handle, hw_params, channels)) < 0) {
      fprintf (stderr, "cannot set channel count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   period_size = period;
   dir = 0;
   if ((err = snd_pcm_hw_params_set_period_size_near (dev->capture_handle, hw_params, &period_size, &dir)) < 0) {
      fprintf (stderr, "cannot set period size (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params_set_periods (dev->capture_handle, hw_params, PERIODS, 0)) < 0) {
      fprintf (stderr, "cannot set number of periods (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   buffer_size = period_size * PERIODS;
   dir=0;
   if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->capture_handle, hw_params, &buffer_size)) < 0) {
      fprintf (stderr, "cannot set buffer time (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params (dev->capture_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot set capture parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/
   snd_pcm_hw_params_free (hw_params);

   if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
      fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_current (dev->capture_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_avail_min (dev->capture_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set minimum available count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params (dev->capture_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot set software parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }   
   
   
   if ((err = snd_pcm_open (&dev->playback_handle, dev->device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
      fprintf (stderr, "cannot open audio device %s (%s)\n",
               dev->device_name,
               snd_strerror (err));
      assert(0);
   }
   
   if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
      fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_any (dev->playback_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_access (dev->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
      fprintf (stderr, "cannot set access type (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_format (dev->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
      fprintf (stderr, "cannot set sample format (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   if ((err = snd_pcm_hw_params_set_rate_near (dev->playback_handle, hw_params, &rate, 0)) < 0) {
      fprintf (stderr, "cannot set sample rate (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   /*fprintf (stderr, "rate = %d\n", rate);*/

   if ((err = snd_pcm_hw_params_set_channels (dev->playback_handle, hw_params, channels)) < 0) {
      fprintf (stderr, "cannot set channel count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   period_size = period;
   dir = 0;
   if ((err = snd_pcm_hw_params_set_period_size_near (dev->playback_handle, hw_params, &period_size, &dir)) < 0) {
      fprintf (stderr, "cannot set period size (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_hw_params_set_periods (dev->playback_handle, hw_params, PERIODS, 0)) < 0) {
      fprintf (stderr, "cannot set number of periods (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   buffer_size = period_size * PERIODS;
   dir=0;
   if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->playback_handle, hw_params, &buffer_size)) < 0) {
      fprintf (stderr, "cannot set buffer time (%s)\n",
               snd_strerror (err));
      assert(0);
   }


   if ((err = snd_pcm_hw_params (dev->playback_handle, hw_params)) < 0) {
      fprintf (stderr, "cannot set playback parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }

   /*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/
   snd_pcm_hw_params_free (hw_params);

   
   if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
      fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_current (dev->playback_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_avail_min (dev->playback_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set minimum available count (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params_set_start_threshold (dev->playback_handle, sw_params, period)) < 0) {
      fprintf (stderr, "cannot set start mode (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_sw_params (dev->playback_handle, sw_params)) < 0) {
      fprintf (stderr, "cannot set software parameters (%s)\n",
               snd_strerror (err));
      assert(0);
   }
  
   
   snd_pcm_link(dev->capture_handle, dev->playback_handle);
   if ((err = snd_pcm_prepare (dev->capture_handle)) < 0) {
      fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   if ((err = snd_pcm_prepare (dev->playback_handle)) < 0) {
      fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   dev->readN = snd_pcm_poll_descriptors_count(dev->capture_handle);
   dev->writeN = snd_pcm_poll_descriptors_count(dev->playback_handle);

   dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd));
   /*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/
   if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN)
   {
      fprintf (stderr, "cannot obtain capture file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   
   dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd));
   if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN)
   {
      fprintf (stderr, "cannot obtain playback file descriptors (%s)\n",
               snd_strerror (err));
      assert(0);
   }
   return dev;
}
Пример #20
0
bool QAudioInputPrivate::open( QObject *input )
{
    // Open the Alsa capture device.
    bool    rc = true;
    int     err;

    unsigned int        freakuency = frequency;

    if ((err = snd_pcm_open(&handle,
                             m_device.constData(), //"plughw:0,0"
                             SND_PCM_STREAM_CAPTURE,
                                 0/*SND_PCM_ASYNC*/)) < 0) {

        qWarning( "QAudioInput: snd_pcm_open: error %d", err);

        rc = false;
    }
    else {
        snd_pcm_hw_params_t *hwparams;

        // We want non-blocking mode.
        snd_pcm_nonblock(handle, 1);

        // Set the desired parameters.
        snd_pcm_hw_params_alloca(&hwparams);

        err = snd_pcm_hw_params_any(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_any: err %d", err);
        }

        err = snd_pcm_hw_params_set_access(handle, hwparams,
                                           access);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_access: err %d",err);
        }

        err = snd_pcm_hw_params_set_format(handle, hwparams,format);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_format: err %d",err);
        }

        err = snd_pcm_hw_params_set_channels(handle,hwparams,(unsigned int)channels);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_channels: err %d",err);
        }

        err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
        }
        if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
            qWarning("QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
        }

        if ( samplesPerBlock != -1 ) {
            // Set buffer and period sizes based on the supplied block size.
            sample_size = (snd_pcm_uframes_t)( samplesPerBlock * channels / 8 );
            err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &freakuency, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_rate_near: err %d",err);
            }
            if(freakuency > 1.05 * frequency || freakuency < 0.95 * frequency) {
                qWarning( "QAudioInput: warning, sample rate %i not supported by the hardware, using %u", frequency, freakuency);
            }

            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
        } else {
            // Use the largest buffer and period sizes we can.
            err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err %d",err);
            }
            period_time = 1000000 * 256 / frequency;
            err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, 0);
            if ( err < 0 ) {
                qWarning( "QAudioInput: snd_pcm_hw_params_set_period_time_near: err %d",err);
            }
       }

        err = snd_pcm_hw_params(handle, hwparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_hw_params: err %d",err);
        }

        int                  dir;
        unsigned int         vval, vval2;
        snd_pcm_access_t     aval;
        snd_pcm_format_t     fval;
        snd_pcm_subformat_t  sval;

        qLog(QAudioInput) << "PCM handle name = " << snd_pcm_name(handle);
        qLog(QAudioInput) << "PCM state = " << snd_pcm_state_name(snd_pcm_state(handle));

        snd_pcm_hw_params_get_access(hwparams,&aval);
        vval = (unsigned int)aval;
        if ( (int)vval != (int)access ) {
            qLog(QAudioInput) << QString("access type not set, want %1 got %2")
                       .arg(snd_pcm_access_name((snd_pcm_access_t)access))
                       .arg(snd_pcm_access_name((snd_pcm_access_t)vval));
            access = (snd_pcm_access_t)vval;
        }
        qLog(QAudioInput) << "access type = " << snd_pcm_access_name((snd_pcm_access_t)vval);

        snd_pcm_hw_params_get_format(hwparams, &fval);
        vval = (unsigned int)fval;
        if ( (int)vval != (int)format ) {
            qLog(QAudioInput) << QString("format type not set, want %1 got %2")
                       .arg(snd_pcm_format_name((snd_pcm_format_t)format))
                       .arg(snd_pcm_format_name((snd_pcm_format_t)vval));
            format = (snd_pcm_format_t)vval;
        }
        qLog(QAudioInput) << QString("format = '%1' (%2)")
            .arg(snd_pcm_format_name((snd_pcm_format_t)vval))
            .arg(snd_pcm_format_description((snd_pcm_format_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_subformat(hwparams,&sval);
        vval = (unsigned int)sval;
        qLog(QAudioInput) << QString("subformat = '%1' (%2)")
            .arg(snd_pcm_subformat_name((snd_pcm_subformat_t)vval))
            .arg(snd_pcm_subformat_description((snd_pcm_subformat_t)vval))
            .toLatin1().constData();

        snd_pcm_hw_params_get_channels(hwparams, &vval);
        if ( (int)vval != (int)channels ) {
            qLog(QAudioInput) << QString("channels type not set, want %1 got %2").arg(channels).arg(vval);
            channels = vval;
        }
        qLog(QAudioInput) << "channels = " << vval;

        snd_pcm_hw_params_get_rate(hwparams, &vval, &dir);
        if ( (int)vval != (int)frequency ) {
            qLog(QAudioInput) << QString("frequency type not set, want %1 got %2").arg(frequency).arg(vval);
            frequency = vval;
        }
        qLog(QAudioInput) << "rate =" <<  vval << " bps";

        snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
        qLog(QAudioInput) << "period time =" << period_time << " us";
        snd_pcm_hw_params_get_period_size(hwparams,&period_size, &dir);
        qLog(QAudioInput) << "period size =" << (int)period_size;
        snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
        qLog(QAudioInput) << "buffer time =" << buffer_time;
        snd_pcm_hw_params_get_buffer_size(hwparams,(snd_pcm_uframes_t *) &buffer_size);
        qLog(QAudioInput) << "buffer size =" << (int)buffer_size;
        snd_pcm_hw_params_get_periods(hwparams, &vval, &dir);
        qLog(QAudioInput) << "periods per buffer =" << vval;
        snd_pcm_hw_params_get_rate_numden(hwparams, &vval, &vval2);
        qLog(QAudioInput) << QString("exact rate = %1/%2 bps").arg(vval).arg(vval2).toLatin1().constData();
        vval = snd_pcm_hw_params_get_sbits(hwparams);
        qLog(QAudioInput) << "significant bits =" << vval;
        snd_pcm_hw_params_get_tick_time(hwparams,&vval, &dir);
        qLog(QAudioInput) << "tick time =" << vval;
        vval = snd_pcm_hw_params_is_batch(hwparams);
        qLog(QAudioInput) << "is batch =" << vval;
        vval = snd_pcm_hw_params_is_block_transfer(hwparams);
        qLog(QAudioInput) << "is block transfer =" << vval;
        vval = snd_pcm_hw_params_is_double(hwparams);
        qLog(QAudioInput) << "is double =" << vval;
        vval = snd_pcm_hw_params_is_half_duplex(hwparams);
        qLog(QAudioInput) << "is half duplex =" << vval;
        vval = snd_pcm_hw_params_is_joint_duplex(hwparams);
        qLog(QAudioInput) << "is joint duplex =" << vval;
        vval = snd_pcm_hw_params_can_overrange(hwparams);
        qLog(QAudioInput) << "can overrange =" << vval;
        vval = snd_pcm_hw_params_can_mmap_sample_resolution(hwparams);
        qLog(QAudioInput) << "can mmap =" << vval;
        vval = snd_pcm_hw_params_can_pause(hwparams);
        qLog(QAudioInput) << "can pause =" << vval;
        vval = snd_pcm_hw_params_can_resume(hwparams);
        qLog(QAudioInput) << "can resume =" << vval;
        vval = snd_pcm_hw_params_can_sync_start(hwparams);
        qLog(QAudioInput) << "can sync start =" << vval;

        snd_pcm_sw_params_t *swparams;
        snd_pcm_sw_params_alloca(&swparams);
        err = snd_pcm_sw_params_current(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_current: err %d",err);
        }
        err = snd_pcm_sw_params_set_start_threshold(handle,swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_start_threshold: err %d",err);
        }
        err = snd_pcm_sw_params_set_avail_min(handle, swparams,period_size);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_avail_min: err %d",err);
        }
        err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params_set_xfer_align: err %d",err);
        }
        err = snd_pcm_sw_params(handle, swparams);
        if ( err < 0 ) {
            qWarning( "QAudioInput: snd_pcm_sw_params: err %d",err);
        }

        snd_pcm_prepare(handle);
        snd_pcm_start(handle);

        int     count = snd_pcm_poll_descriptors_count(handle);
        pollfd  *pfds = new pollfd[count];

        snd_pcm_poll_descriptors(handle, pfds, count);

        for (int i = 0; i < count; ++i)
        {
            if ((pfds[i].events & POLLIN) != 0) {
                notifier = new QSocketNotifier(pfds[i].fd, QSocketNotifier::Read);
                QObject::connect(notifier,
                                 SIGNAL(activated(int)),
                                 input,
                                 SIGNAL(readyRead()));

                break;
            }
        }

        if (notifier == NULL) {
            rc = false;
        }

        delete pfds;
    }

    return rc;
}
Пример #21
0
static int audio_open(audiodevice_t *dev, chanfmt_t fmt) {
	audio_alsa09_t *alsa = (audio_alsa09_t *)dev->data_pcm;
	struct pollfd pfds;
	snd_pcm_hw_params_t *hwparams;
#if SND_LIB_VERSION >= SND_PROTOCOL_VERSION(1,0,0)
	snd_pcm_uframes_t len;
#else
	snd_pcm_sframes_t len;
#endif
	int err, periods;
	
	if (0 > snd_pcm_open(&alsa->handle, alsa->dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_ASYNC)) {
		WARNING("Opening audio device %d failed\n", alsa->dev);
		goto _err_exit;
	}
	snd_pcm_hw_params_alloca(&hwparams);
	
	if (0 > snd_pcm_hw_params_any(alsa->handle, hwparams)) {
		WARNING("param get failed\n");
		goto _err_exit;
	}
	
	if (0 > snd_pcm_hw_params_set_access(alsa->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) {
		WARNING("set access fail\n");
		goto _err_exit;
	}
	
	if (0 > snd_pcm_hw_params_set_format(alsa->handle, hwparams, fmt.bit == 16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8)) {
		WARNING("set format fail\n");
		goto _err_exit;
	}
	
	if (0 > snd_pcm_hw_params_set_channels(alsa->handle, hwparams, fmt.ch)) {
		WARNING("set channel fail\n");
		goto _err_exit;
	}
	
#if SND_LIB_VERSION >= SND_PROTOCOL_VERSION(1,0,0)
	int tmp = fmt.rate;
	err = snd_pcm_hw_params_set_rate_near(alsa->handle, hwparams, &tmp, 0);
#else
	err = snd_pcm_hw_params_set_rate_near(alsa->handle, hwparams, fmt.rate, 0);
#endif
	if (err < 0) {
		WARNING("set rate fail\n");
		goto _err_exit;
	}

	if (tmp != fmt.rate) {
		WARNING("set rate fail\n");
		goto _err_exit;
	}

	if (0 > snd_pcm_hw_params_set_periods_integer(alsa->handle, hwparams)) {
		WARNING("set periods fail\n");
		goto _err_exit;
	}
	
	periods = 2;
	if (0 > snd_pcm_hw_params_set_periods_min(alsa->handle, hwparams, &periods, 0)) {
		WARNING("set priods min fail\n");
		goto _err_exit;
	}
	
	if (0 > snd_pcm_hw_params_set_buffer_size(alsa->handle, hwparams, BUFFERSIZE)) {
		WARNING("set buffer fail\n");
		goto _err_exit;
	}	  
	
	if (0 > snd_pcm_hw_params(alsa->handle, hwparams)) {
		WARNING("set hw parmas fail\n");
		goto _err_exit;
	}	  
#if SND_LIB_VERSION >= SND_PROTOCOL_VERSION(1,0,0)
	
        snd_pcm_hw_params_get_buffer_size(hwparams, &len);
#else
	len = snd_pcm_hw_params_get_buffer_size(hwparams);
#endif
	dev->buf.len = (int)len;
	snd_pcm_poll_descriptors(alsa->handle, &pfds, 1);
	dev->fd = pfds.fd;
	return OK;
	
 _err_exit:
	if (alsa->handle) {
		snd_pcm_close(alsa->handle);
	}
	dev->fd = -1;
	return NG;
}
Пример #22
0
bool
AlsaSource::InitializeAlsa ()
{
	bool res = false;
	int result;
	AudioStream *stream = NULL;
	
	LOG_AUDIO ("AlsaSource::InitializeAlsa (%p) initialized: %i\n", this, initialized);
	
	mutex.Lock ();
	
	if (initialized) {
		result = true;
		goto cleanup;
	}
	
	stream = GetStreamReffed ();
		
	if (stream == NULL) {
		// Shouldn't really happen, but handle this case anyway.
		LOG_AUDIO ("AlsaSource::Initialize (): trying to initialize an audio device, but there's no audio to play.\n");
		goto cleanup;
	}
		
	// Open a pcm device
	result = snd_pcm_open (&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0 /*SND_PCM_NONBLOCK*/);
	if (result != 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): cannot open audio device: %s\n", snd_strerror (result));
		pcm = NULL;
		goto cleanup;
	}

	// Configure the hardware
	if (!SetupHW ()) {
		LOG_AUDIO ("AlsaSource::Initialize (): could not configure hardware for audio playback\n");
		Close ();
		goto cleanup;
	}
	
	result = snd_pcm_get_params (pcm, &buffer_size, &period_size);
	if (result != 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): error while getting parameters: %s\n", snd_strerror (result));
		Close ();
		goto cleanup;
	}

	// Get the file descriptors to poll on
	ndfs = snd_pcm_poll_descriptors_count (pcm);
	if (ndfs <= 0) {
		LOG_AUDIO ("AlsaSource::Initialize(): Unable to initialize audio for playback (could not get poll descriptor count).\n");
		Close ();
		goto cleanup;
	}

	udfs = (pollfd *) g_malloc0 (sizeof (pollfd) * ndfs);
	if (snd_pcm_poll_descriptors (pcm, udfs, ndfs) < 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): Unable to initialize audio for playback (could not get poll descriptors).\n");
		Close ();
		goto cleanup;
	}
	
	LOG_AUDIO ("AlsaSource::Initialize (%p): Succeeded. Buffer size: %lu, period size: %lu\n", this, buffer_size, period_size);

	res = true;
	initialized = true;
	
cleanup:

	mutex.Unlock ();

	if (stream)
		stream->unref ();

	return res;
}
Пример #23
0
int snd_pcm_generic_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
{
    snd_pcm_generic_t *generic = pcm->private_data;
    return snd_pcm_poll_descriptors(generic->slave, pfds, space);
}
Пример #24
0
static
audio_stream *
alsa_create_stream(audio_stream_direction direction, unsigned int sample_rate,
                   unsigned int sample_frame_count, const char *pcm_name)
{
    audio_stream *as;
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_sw_params_t *sw_params;
    int dir;

    if (!g_atomic_int_get(&audio_thread_started)) {
        pthread_barrier_init(&stream_list_update_barrier, NULL, 2);
        pthread_create(&audio_thread_id, NULL, audio_thread, NULL);
        g_atomic_int_set(&audio_thread_started, 1);
        pthread_barrier_wait(&stream_list_update_barrier);
    }

    as = calloc(1, sizeof(*as));
    if (!as)
        goto err;

    as->sample_frame_count = sample_frame_count;
    g_atomic_int_set(&as->paused, 1);

#define CHECK_A(funcname, params)                                                       \
    do {                                                                                \
        int errcode___ = funcname params;                                               \
        if (errcode___ < 0) {                                                           \
            trace_error("%s, " #funcname ", %s\n", __func__, snd_strerror(errcode___)); \
            goto err;                                                                   \
        }                                                                               \
    } while (0)

    if (direction == STREAM_PLAYBACK)
        CHECK_A(snd_pcm_open, (&as->pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0));
    else
        CHECK_A(snd_pcm_open, (&as->pcm, pcm_name, SND_PCM_STREAM_CAPTURE, 0));

    CHECK_A(snd_pcm_hw_params_malloc, (&hw_params));
    CHECK_A(snd_pcm_hw_params_any, (as->pcm, hw_params));
    CHECK_A(snd_pcm_hw_params_set_access, (as->pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED));
    CHECK_A(snd_pcm_hw_params_set_format, (as->pcm, hw_params, SND_PCM_FORMAT_S16_LE));
    dir = 0;
    unsigned int rate = sample_rate;
    CHECK_A(snd_pcm_hw_params_set_rate_near, (as->pcm, hw_params, &rate, &dir));

    const int channel_count = (direction == STREAM_PLAYBACK) ? 2 : 1;
    CHECK_A(snd_pcm_hw_params_set_channels, (as->pcm, hw_params, channel_count));

    unsigned int period_time = (long long)sample_frame_count * 1000 * 1000 / sample_rate;
    period_time = CLAMP(period_time,
                        1000 * (unsigned int)config.audio_buffer_min_ms,
                        1000 * (unsigned int)config.audio_buffer_max_ms);
    dir = 1;
    CHECK_A(snd_pcm_hw_params_set_period_time_near, (as->pcm, hw_params, &period_time, &dir));

    unsigned int buffer_time = 4 * period_time;
    dir = 1;
    CHECK_A(snd_pcm_hw_params_set_buffer_time_near, (as->pcm, hw_params, &buffer_time, &dir));

    dir = 0;
    CHECK_A(snd_pcm_hw_params_get_buffer_time, (hw_params, &buffer_time, &dir));
    CHECK_A(snd_pcm_hw_params, (as->pcm, hw_params));
    snd_pcm_hw_params_free(hw_params);

    CHECK_A(snd_pcm_sw_params_malloc, (&sw_params));
    CHECK_A(snd_pcm_sw_params_current, (as->pcm, sw_params));
    CHECK_A(snd_pcm_sw_params, (as->pcm, sw_params));
    CHECK_A(snd_pcm_prepare, (as->pcm));
    snd_pcm_sw_params_free(sw_params);

    CHECK_A(snd_pcm_prepare, (as->pcm));

    if (direction == STREAM_CAPTURE)
        CHECK_A(snd_pcm_start, (as->pcm));

    as->nfds = snd_pcm_poll_descriptors_count(as->pcm);
    as->fds = calloc(as->nfds, sizeof(struct pollfd));
    if (!as->fds) {
        trace_error("%s, memory allocation failure\n", __func__);
        goto err;
    }
    snd_pcm_poll_descriptors(as->pcm, as->fds, as->nfds);

    g_hash_table_insert(active_streams_ht, as, GINT_TO_POINTER(1));
    for (uintptr_t k = 0; k < as->nfds; k ++)
        g_hash_table_insert(stream_by_fd_ht, GINT_TO_POINTER(as->fds[k].fd), as);

    wakeup_audio_thread();

#undef CHECK_A

    return as;
err:
    free(as);
    return NULL;
}
Пример #25
0
int main(int argc, char *argv[]) {
    const char *dev;
    int r, cap, count = 0;
    snd_pcm_hw_params_t *hwparams;
    snd_pcm_sw_params_t *swparams;
    snd_pcm_status_t *status;
    snd_pcm_t *pcm;
    unsigned rate = 44100;
    unsigned periods = 2;
    snd_pcm_uframes_t boundary, buffer_size = 44100/10; /* 100s */
    int dir = 1;
    struct timespec start, last_timestamp = { 0, 0 };
    uint64_t start_us, last_us = 0;
    snd_pcm_sframes_t last_avail = 0, last_delay = 0;
    struct pollfd *pollfds;
    int n_pollfd;
    int64_t sample_count = 0;
    struct sched_param sp;

    r = -1;
#ifdef _POSIX_PRIORITY_SCHEDULING
    sp.sched_priority = 5;
    r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
#endif
    if (r)
        printf("Could not get RT prio. :(\n");

    snd_pcm_hw_params_alloca(&hwparams);
    snd_pcm_sw_params_alloca(&swparams);
    snd_pcm_status_alloca(&status);

    r = clock_gettime(CLOCK_MONOTONIC, &start);
    assert(r == 0);

    start_us = timespec_us(&start);

    dev = argc > 1 ? argv[1] : "front:AudioPCI";
    cap = argc > 2 ? atoi(argv[2]) : 0;

    if (cap == 0)
      r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
    else
      r = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_CAPTURE, 0);
    assert(r == 0);

    r = snd_pcm_hw_params_any(pcm, hwparams);
    assert(r == 0);

    r = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 0);
    assert(r == 0);

    r = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    assert(r == 0);

    r = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE);
    assert(r == 0);

    r = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, NULL);
    assert(r == 0);

    r = snd_pcm_hw_params_set_channels(pcm, hwparams, 2);
    assert(r == 0);

    r = snd_pcm_hw_params_set_periods_integer(pcm, hwparams);
    assert(r == 0);

    r = snd_pcm_hw_params_set_periods_near(pcm, hwparams, &periods, &dir);
    assert(r == 0);

    r = snd_pcm_hw_params_set_buffer_size_near(pcm, hwparams, &buffer_size);
    assert(r == 0);

    r = snd_pcm_hw_params(pcm, hwparams);
    assert(r == 0);

    r = snd_pcm_hw_params_current(pcm, hwparams);
    assert(r == 0);

    r = snd_pcm_sw_params_current(pcm, swparams);
    assert(r == 0);

    if (cap == 0)
      r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 1);
    else
      r = snd_pcm_sw_params_set_avail_min(pcm, swparams, 0);
    assert(r == 0);

    r = snd_pcm_sw_params_set_period_event(pcm, swparams, 0);
    assert(r == 0);

    r = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
    assert(r == 0);
    r = snd_pcm_sw_params_set_start_threshold(pcm, swparams, buffer_size);
    assert(r == 0);

    r = snd_pcm_sw_params_get_boundary(swparams, &boundary);
    assert(r == 0);
    r = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary);
    assert(r == 0);

    r = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE);
    assert(r == 0);

    r = snd_pcm_sw_params(pcm, swparams);
    assert(r == 0);

    r = snd_pcm_prepare(pcm);
    assert(r == 0);

    r = snd_pcm_sw_params_current(pcm, swparams);
    assert(r == 0);

/*     assert(snd_pcm_hw_params_is_monotonic(hwparams) > 0); */

    n_pollfd = snd_pcm_poll_descriptors_count(pcm);
    assert(n_pollfd > 0);

    pollfds = malloc(sizeof(struct pollfd) * n_pollfd);
    assert(pollfds);

    r = snd_pcm_poll_descriptors(pcm, pollfds, n_pollfd);
    assert(r == n_pollfd);

    printf("Starting. Buffer size is %u frames\n", (unsigned int) buffer_size);

    if (cap) {
      r = snd_pcm_start(pcm);
      assert(r == 0);
    }

    for (;;) {
        snd_pcm_sframes_t avail, delay;
        struct timespec now, timestamp;
        unsigned short revents;
        int handled = 0;
        uint64_t now_us, timestamp_us;
        snd_pcm_state_t state;
        unsigned long long pos;

        r = poll(pollfds, n_pollfd, 0);
        assert(r >= 0);

        r = snd_pcm_poll_descriptors_revents(pcm, pollfds, n_pollfd, &revents);
        assert(r == 0);

        if (cap == 0)
          assert((revents & ~POLLOUT) == 0);
        else
          assert((revents & ~POLLIN) == 0);

        avail = snd_pcm_avail(pcm);
        assert(avail >= 0);

        r = snd_pcm_status(pcm, status);
        assert(r == 0);

        /* This assertion fails from time to time. ALSA seems to be broken */
/*         assert(avail == (snd_pcm_sframes_t) snd_pcm_status_get_avail(status)); */
/*         printf("%lu %lu\n", (unsigned long) avail, (unsigned long) snd_pcm_status_get_avail(status)); */

        snd_pcm_status_get_htstamp(status, &timestamp);
        delay = snd_pcm_status_get_delay(status);
        state = snd_pcm_status_get_state(status);

        r = clock_gettime(CLOCK_MONOTONIC, &now);
        assert(r == 0);

        assert(!revents || avail > 0);

        if ((!cap && avail) || (cap && (unsigned)avail >= buffer_size)) {
            snd_pcm_sframes_t sframes;
            static const uint16_t psamples[2] = { 0, 0 };
            uint16_t csamples[2];

            if (cap == 0)
              sframes = snd_pcm_writei(pcm, psamples, 1);
            else
              sframes = snd_pcm_readi(pcm, csamples, 1);
            assert(sframes == 1);

            handled = 1;
            sample_count++;
        }

        if (!handled &&
            memcmp(&timestamp, &last_timestamp, sizeof(timestamp)) == 0 &&
            avail == last_avail &&
            delay == last_delay) {
            /* This is boring */
            continue;
        }

        now_us = timespec_us(&now);
        timestamp_us = timespec_us(&timestamp);

        if (cap == 0)
            pos = (unsigned long long) ((sample_count - handled - delay) * 1000000LU / 44100);
        else
            pos = (unsigned long long) ((sample_count - handled + delay) * 1000000LU / 44100);

        if (count++ % 50 == 0)
            printf("Elapsed\tCPU\tALSA\tPos\tSamples\tavail\tdelay\trevents\thandled\tstate\n");

        printf("%llu\t%llu\t%llu\t%llu\t%llu\t%li\t%li\t%i\t%i\t%i\n",
               (unsigned long long) (now_us - last_us),
               (unsigned long long) (now_us - start_us),
               (unsigned long long) (timestamp_us ? timestamp_us - start_us : 0),
               pos,
               (unsigned long long) sample_count,
               (signed long) avail,
               (signed long) delay,
               revents,
               handled,
               state);

        if (cap == 0)
          /** When this assert is hit, most likely something bad
           * happened, i.e. the avail jumped suddenly. */
          assert((unsigned) avail <= buffer_size);

        last_avail = avail;
        last_delay = delay;
        last_timestamp = timestamp;
        last_us = now_us;
    }

    return 0;
}
Пример #26
0
bool WaveRecorder::init(uint32_t samples_per_sec,
                        uint32_t bits_per_sample,
                        uint32_t channels,
                        uint32_t frame_size)
{
    const char* pcm_device = "default";
    snd_pcm_format_t format;
    int err;

    _frame_size = frame_size;

    switch (bits_per_sample) {
    case 8:
        format = SND_PCM_FORMAT_S8;
        break;
    case 16:
        format = SND_PCM_FORMAT_S16_LE;
        break;
    default:
        return false;
    }

    if ((err = snd_pcm_open(&_pcm, pcm_device, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
        LOG_ERROR("cannot open audio record device %s %s", pcm_device, snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_malloc(&_hw_params)) < 0) {
        LOG_ERROR("cannot allocate hardware parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_malloc(&_sw_params)) < 0) {
        LOG_ERROR("cannot allocate software parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_any(_pcm, _hw_params)) < 0) {
        LOG_ERROR("cannot initialize hardware parameter structure %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_rate_resample(_pcm, _hw_params, 1)) < 0) {
        LOG_ERROR("cannot set rate resample %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_access(_pcm, _hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        LOG_ERROR("cannot set access type %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_rate(_pcm, _hw_params, samples_per_sec, 0)) < 0) {
        LOG_ERROR("cannot set sample rate %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_channels(_pcm, _hw_params, channels)) < 0) {
        LOG_ERROR("cannot set channel count %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params_set_format(_pcm, _hw_params, format)) < 0) {
        LOG_ERROR("cannot set sample format %s", snd_strerror(err));
        return false;
    }

    int direction = 0;
    snd_pcm_uframes_t buffer_size = (samples_per_sec * 160 / 1000) / frame_size * frame_size;

    if ((err = snd_pcm_hw_params_set_buffer_size_near(_pcm, _hw_params, &buffer_size)) < 0) {
        LOG_ERROR("cannot set buffer size %s", snd_strerror(err));
        return false;
    }

    snd_pcm_uframes_t period_size = frame_size;
    if ((err = snd_pcm_hw_params_set_period_size_near(_pcm, _hw_params, &period_size,
                                                      &direction)) < 0) {
        LOG_ERROR("cannot set period size near %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_hw_params(_pcm, _hw_params)) < 0) {
        LOG_ERROR("cannot set parameters %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_current(_pcm, _sw_params)) < 0) {
        LOG_ERROR("cannot get current sw parameters %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params_set_start_threshold(_pcm, _sw_params, frame_size)) < 0) {
        LOG_ERROR("cannot set start threshold %s", snd_strerror(err));
        return false;
    }

    if ((err = snd_pcm_sw_params(_pcm, _sw_params)) < 0) {
        LOG_ERROR("cannot set sw parameters %s", snd_strerror(err));
        return false;
    }

    struct pollfd pfd;
    if ((err = snd_pcm_poll_descriptors(_pcm, &pfd, 1)) < 0) {
        LOG_ERROR("cannot get poll ID %s", snd_strerror(err));
        return false;
    }
    _event_trigger = new WaveRecorder::EventTrigger(*this, pfd.fd);
    _client.add_event_source(*_event_trigger);
    return true;
}
Пример #27
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    gint mf, err, pers;

    if(pcm_open_and_load_hwparams(d) < 0)
	goto out;

    // ---
    // Set non-blocking mode.
    // ---

    d->outtime = 0;

    // --
    // Set channel parameters
    // --
    if((err = snd_pcm_hw_params_set_access(d->soundfd, d->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
	alsa_error(N_("Unable to set access"), err);
	goto out;
    }

    if((err = snd_pcm_hw_params_set_format(d->soundfd, d->hwparams,
				    (d->bits - 8) ? d->signedness16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U16 :
						    d->signedness8 ? SND_PCM_FORMAT_S8 : SND_PCM_FORMAT_U8) < 0)) {
	alsa_error(N_("Unable to set audio format"), err);
	goto out;
    }
    /* Handle endianess aspects. TODO! */
    switch(d->bits) {
	case 16:
	    mf = d->signedness16 ? ST_MIXER_FORMAT_S16_LE : ST_MIXER_FORMAT_U16_LE;
	    break;
	case 8:
	default:
	    mf = d->signedness8 ? ST_MIXER_FORMAT_S8 : ST_MIXER_FORMAT_U8;
	    break;
    }

    if((err = snd_pcm_hw_params_set_channels(d->soundfd, d->hwparams, d->stereo + 1)) < 0) {
	alsa_error(N_("Unable to set channels number"), err);
	goto out;
    }
    if((d->stereo)) {
	mf |= ST_MIXER_FORMAT_STEREO;
    }
    d->mf = mf;

    d->p_mixfreq = d->playrate;
    if ((err = snd_pcm_hw_params_set_rate_near(d->soundfd, d->hwparams, &(d->p_mixfreq), NULL)) < 0) {
	alsa_error(N_("Unable to set sample rate"), err);
	goto out;
    }

    if(snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size) < 0) {
	/* Some soundcards report wrong maximal buffer size (maybe alsa bug). So we should try
	   to downscale its value before the reporting an error. The spinbutton still may display
	   the wrong number, but actually the correct value will be implemented.*/
	while((--d->buffer_size) >= 8)
	    if(!snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size))
		break;
	if(d->buffer_size < 8) {
	    error_error(N_("Unable to set appropriate buffer size"));
	    goto out;
	}
    }
    pers = 1 << d->num_periods;
    if ((err = snd_pcm_hw_params_set_periods_near(d->soundfd, d->hwparams, &pers, NULL)) < 0) {
	alsa_error(N_("Unable to set periods number"), err);
	goto out;
    }
    if ((err = snd_pcm_hw_params_get_period_size(d->hwparams, &(d->p_fragsize), NULL)) < 0) {
	alsa_error(N_("Unable to get period size"), err);
	goto out;
    }

    if((err = snd_pcm_hw_params(d->soundfd, d->hwparams))) {
	alsa_error(N_("Error setting hw parameters"), err);
	goto out;
    }

    /* The following piece of code is directly c_n_p'ed from the ALSA pcm example (whith a little adopting) */
    /* get the current swparams */
    err = snd_pcm_sw_params_current(d->soundfd, d->swparams);
    if (err < 0) {
            alsa_error(N_("Unable to determine current swparams for playback"), err);
	    goto out;
    }
    /* start the transfer when the buffer is full */
    err = snd_pcm_sw_params_set_start_threshold(d->soundfd, d->swparams, d->p_fragsize);
    if (err < 0) {
            alsa_error(N_("Unable to set start threshold mode for playback"), err);
	    goto out;
    }
    /* allow the transfer when at least period_size samples can be processed */
    err = snd_pcm_sw_params_set_avail_min(d->soundfd, d->swparams, d->p_fragsize);
    if (err < 0) {
            alsa_error(N_("Unable to set avail min for playback"), err);
	    goto out;
    }
    /* align all transfers to 1 sample */
    err = snd_pcm_sw_params_set_xfer_align(d->soundfd, d->swparams, 1);
    if (err < 0) {
            alsa_error(N_("Unable to set transfer align for playback"), err);
	    goto out;
    }
    /* write the parameters to the playback device */
    err = snd_pcm_sw_params(d->soundfd, d->swparams);
    if (err < 0) {
            alsa_error(N_("Unable to set sw params for playback"), err);
	    goto out;
    }

    err = snd_pcm_prepare(d->soundfd);
    if (err < 0) {
            alsa_error(N_("Unable to prepare playback"), err);
	    goto out;
    }
    // ---
    // Get buffering parameters
    // ---
   
    if(d->verbose)
        snd_pcm_dump(d->soundfd, d->output);
    d->sndbuf = calloc((d->stereo + 1) * (d->bits / 8), d->p_fragsize);

    d->pfd = malloc(sizeof(struct pollfd));
    if ((err = snd_pcm_poll_descriptors(d->soundfd, d->pfd, 1)) < 0) {
        alsa_error(N_("Unable to obtain poll descriptors for playback"), err);
        goto out;
    }

    d->polltag = audio_poll_add(d->pfd->fd, GDK_INPUT_WRITE, alsa_poll_ready_playing, d);

    d->playtime = 0;
    d->firstpoll = TRUE;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}
Пример #28
0
int
cubeb_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
                  cubeb_stream_params stream_params, unsigned int latency,
                  cubeb_data_callback data_callback, cubeb_state_callback state_callback,
                  void * user_ptr)
{
  cubeb_stream * stm;
  int r;
  snd_pcm_format_t format;
  snd_pcm_uframes_t buffer_size;
  snd_pcm_uframes_t period_size;

  assert(context);
  assert(stream);

  if (stream_params.rate < 1 || stream_params.rate > 192000 ||
      stream_params.channels < 1 || stream_params.channels > 32 ||
      latency < 1 || latency > 2000) {
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  switch (stream_params.format) {
  case CUBEB_SAMPLE_S16LE:
    format = SND_PCM_FORMAT_S16_LE;
    break;
  case CUBEB_SAMPLE_S16BE:
    format = SND_PCM_FORMAT_S16_BE;
    break;
  case CUBEB_SAMPLE_FLOAT32LE:
    format = SND_PCM_FORMAT_FLOAT_LE;
    break;
  case CUBEB_SAMPLE_FLOAT32BE:
    format = SND_PCM_FORMAT_FLOAT_BE;
    break;
  default:
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  stm = calloc(1, sizeof(*stm));
  assert(stm);

  stm->context = context;
  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->user_ptr = user_ptr;
  stm->params = stream_params;

  r = pthread_mutex_init(&stm->lock, NULL);
  assert(r == 0);

  r = pthread_cond_init(&stm->cond, NULL);
  assert(r == 0);

  r = cubeb_locked_pcm_open(&stm->pcm, SND_PCM_STREAM_PLAYBACK);
  if (r < 0) {
    cubeb_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  r = snd_pcm_nonblock(stm->pcm, 1);
  assert(r == 0);

  r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED,
                         stm->params.channels, stm->params.rate, 1,
                         latency * 1000);
  if (r < 0) {
    /* XXX: return format error if necessary */
    cubeb_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  r = snd_pcm_get_params(stm->pcm, &buffer_size, &period_size);
  assert(r == 0);
  fprintf(stderr, "b=%u p=%u\n", buffer_size, period_size);

  /* set up poll infrastructure */

  stm->n_descriptors = snd_pcm_poll_descriptors_count(stm->pcm);
  assert(stm->n_descriptors > 0);

  stm->descriptors = calloc(stm->n_descriptors, sizeof(*stm->descriptors));
  assert(stm->descriptors);

  r = snd_pcm_poll_descriptors(stm->pcm, stm->descriptors, stm->n_descriptors);
  assert(r == stm->n_descriptors);

  r = snd_pcm_pause(stm->pcm, 1);
#if 0
  assert(r == 0);
#endif

  stm->state = CUBEB_STREAM_STATE_INACTIVE;

  *stream = stm;

  return CUBEB_OK;
}
Пример #29
0
static int
alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
                 cubeb_stream_params stream_params, unsigned int latency,
                 cubeb_data_callback data_callback, cubeb_state_callback state_callback,
                 void * user_ptr)
{
  cubeb_stream * stm;
  int r;
  snd_pcm_format_t format;

  assert(ctx && stream);

  *stream = NULL;

  switch (stream_params.format) {
  case CUBEB_SAMPLE_S16LE:
    format = SND_PCM_FORMAT_S16_LE;
    break;
  case CUBEB_SAMPLE_S16BE:
    format = SND_PCM_FORMAT_S16_BE;
    break;
  case CUBEB_SAMPLE_FLOAT32LE:
    format = SND_PCM_FORMAT_FLOAT_LE;
    break;
  case CUBEB_SAMPLE_FLOAT32BE:
    format = SND_PCM_FORMAT_FLOAT_BE;
    break;
  default:
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  pthread_mutex_lock(&ctx->mutex);
  if (ctx->active_streams >= CUBEB_STREAM_MAX) {
    pthread_mutex_unlock(&ctx->mutex);
    return CUBEB_ERROR;
  }
  ctx->active_streams += 1;
  pthread_mutex_unlock(&ctx->mutex);

  stm = calloc(1, sizeof(*stm));
  assert(stm);

  stm->context = ctx;
  stm->data_callback = data_callback;
  stm->state_callback = state_callback;
  stm->user_ptr = user_ptr;
  stm->params = stream_params;
  stm->state = INACTIVE;

  r = pthread_mutex_init(&stm->mutex, NULL);
  assert(r == 0);

  r = alsa_locked_pcm_open(&stm->pcm, SND_PCM_STREAM_PLAYBACK, ctx->local_config);
  if (r < 0) {
    alsa_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  r = snd_pcm_nonblock(stm->pcm, 1);
  assert(r == 0);

  /* Ugly hack: the PA ALSA plugin allows buffer configurations that can't
     possibly work.  See https://bugzilla.mozilla.org/show_bug.cgi?id=761274.
     Only resort to this hack if the handle_underrun workaround failed. */
  if (!ctx->local_config && ctx->is_pa) {
    latency = latency < 500 ? 500 : latency;
  }

  r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED,
                         stm->params.channels, stm->params.rate, 1,
                         latency * 1000);
  if (r < 0) {
    alsa_stream_destroy(stm);
    return CUBEB_ERROR_INVALID_FORMAT;
  }

  r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &stm->period_size);
  assert(r == 0);

  stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm);
  assert(stm->nfds > 0);

  stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd));
  assert(stm->saved_fds);
  r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds);
  assert((nfds_t) r == stm->nfds);

  r = pthread_cond_init(&stm->cond, NULL);
  assert(r == 0);

  if (alsa_register_stream(ctx, stm) != 0) {
    alsa_stream_destroy(stm);
    return CUBEB_ERROR;
  }

  *stream = stm;

  return CUBEB_OK;
}
Пример #30
0
static int wait( PaAlsaStream *stream )
{
    int need_capture;
    int need_playback;
    int capture_avail = INT_MAX;
    int playback_avail = INT_MAX;
    int common_avail;

    if( stream->pcm_capture )
        need_capture = 1;
    else
        need_capture = 0;

    if( stream->pcm_playback )
        need_playback = 1;
    else
        need_playback = 0;

    while( need_capture || need_playback )
    {
        int playback_pfd_offset;
        int total_fds = 0;

        /* if the main thread has requested that we stop, do so now */
        pthread_testcancel();

        /*PA_DEBUG(("still polling...\n"));
        if( need_capture )
            PA_DEBUG(("need capture.\n"));
        if( need_playback )
            PA_DEBUG(("need playback.\n")); */

        /* get the fds, packing all applicable fds into a single array,
         * so we can check them all with a single poll() call */

        if( need_capture )
        {
            snd_pcm_poll_descriptors( stream->pcm_capture, stream->pfds,
                                      stream->capture_nfds );
            total_fds += stream->capture_nfds;
        }

        if( need_playback )
        {
            playback_pfd_offset = total_fds;
            snd_pcm_poll_descriptors( stream->pcm_playback,
                                      stream->pfds + playback_pfd_offset,
                                      stream->playback_nfds );
            total_fds += stream->playback_nfds;
        }

        /* now poll on the combination of playback and capture fds.
         * TODO: handle interrupt and/or failure */
        poll( stream->pfds, total_fds, 1000 );

        /* check the return status of our pfds */
        if( need_capture )
        {
            short revents;
            snd_pcm_poll_descriptors_revents( stream->pcm_capture, stream->pfds,
                                              stream->capture_nfds, &revents );
            if( revents == POLLIN )
                need_capture = 0;
        }

        if( need_playback )
        {
            short revents;
            snd_pcm_poll_descriptors_revents( stream->pcm_playback,
                                              stream->pfds + playback_pfd_offset,
                                              stream->playback_nfds, &revents );
            //if( revents & POLLOUT )
            //if( revents & POLLERR )
            //    PA_DEBUG(("polling error!"));
            if( revents == POLLOUT )
                need_playback = 0;
        }
    }

    /* we have now established that there are buffers ready to be
     * operated on.  Now determine how many frames are available. */
    if( stream->pcm_capture )
        capture_avail = snd_pcm_avail_update( stream->pcm_capture );

    if( stream->pcm_playback )
        playback_avail = snd_pcm_avail_update( stream->pcm_playback );

    common_avail = MIN(capture_avail, playback_avail);
    common_avail -= common_avail % stream->frames_per_period;

    return common_avail;
}