Exemple #1
0
void AudioAlsa::run()
{
	surroundSampleFrame * temp =
		new surroundSampleFrame[mixer()->framesPerPeriod()];
	int_sample_t * outbuf =
			new int_sample_t[mixer()->framesPerPeriod() *
								channels()];
	int_sample_t * pcmbuf = new int_sample_t[m_periodSize * channels()];

	int outbuf_size = mixer()->framesPerPeriod() * channels();
	int outbuf_pos = 0;
	int pcmbuf_size = m_periodSize * channels();

	bool quit = false;
	while( quit == false )
	{
		int_sample_t * ptr = pcmbuf;
		int len = pcmbuf_size;
		while( len )
		{
			if( outbuf_pos == 0 )
			{
				// frames depend on the sample rate
				const fpp_t frames = getNextBuffer( temp );
				if( !frames )
				{
					quit = true;
					memset( ptr, 0, len
						* sizeof( int_sample_t ) );
					break;
				}
				outbuf_size = frames * channels();

				convertToS16( temp, frames,
						mixer()->masterGain(),
						outbuf,
						m_convertEndian );
			}
			int min_len = qMin( len, outbuf_size - outbuf_pos );
			memcpy( ptr, outbuf + outbuf_pos,
					min_len * sizeof( int_sample_t ) );
			ptr += min_len;
			len -= min_len;
			outbuf_pos += min_len;
			outbuf_pos %= outbuf_size;
		}

		f_cnt_t frames = m_periodSize;
		ptr = pcmbuf;

		while( frames )
		{
			int err = snd_pcm_writei( m_handle, ptr, frames );

			if( err == -EAGAIN )
			{
				continue;
			}

			if( err < 0 )
			{
				if( handleError( err ) < 0 )
				{
					printf( "Write error: %s\n",
							snd_strerror( err ) );
				}
				break;	// skip this buffer
			}
			ptr += err * channels();
			frames -= err;
		}
	}

	delete[] temp;
	delete[] outbuf;
	delete[] pcmbuf;
}
Exemple #2
0
static void rdpsnd_alsa_play(rdpsndDevicePlugin* device, uint8* data, int size)
{
    rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*)device;
    uint8* decoded_data;
    int decoded_size;
    uint8* src;
    uint8* resampled_data;
    int len;
    int error;
    int frames;
    int rbytes_per_frame;
    int sbytes_per_frame;
    uint8* pindex;
    uint8* end;

    if (alsa->out_handle == 0)
        return;

    if (alsa->wformat == 0x11)
    {
        decoded_data = dsp_decode_ima_adpcm(&alsa->adpcm,
                                            data, size, alsa->source_channels, alsa->block_size, &decoded_size);
        size = decoded_size;
        src = decoded_data;
    }
    else
    {
        decoded_data = NULL;
        src = data;
    }

    sbytes_per_frame = alsa->source_channels * alsa->bytes_per_channel;
    rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
    if ((size % sbytes_per_frame) != 0)
    {
        DEBUG_WARN("error len mod");
        return;
    }

    if ((alsa->source_rate == alsa->actual_rate) &&
            (alsa->source_channels == alsa->actual_channels))
    {
        resampled_data = NULL;
    }
    else
    {
        resampled_data = dsp_resample(src, alsa->bytes_per_channel,
                                      alsa->source_channels, alsa->source_rate, size / sbytes_per_frame,
                                      alsa->actual_channels, alsa->actual_rate, &frames);
        DEBUG_SVC("resampled %d frames at %d to %d frames at %d",
                  size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
        size = frames * rbytes_per_frame;
        src = resampled_data;
    }

    pindex = src;
    end = pindex + size;
    while (pindex < end)
    {
        len = end - pindex;
        frames = len / rbytes_per_frame;
        error = snd_pcm_writei(alsa->out_handle, pindex, frames);
        if (error == -EPIPE)
        {
            snd_pcm_recover(alsa->out_handle, error, 0);
            error = 0;
        }
        else if (error < 0)
        {
            DEBUG_WARN("error %d", error);
            snd_pcm_close(alsa->out_handle);
            alsa->out_handle = 0;
            rdpsnd_alsa_open(device, NULL, alsa->latency);
            break;
        }
        pindex += error * rbytes_per_frame;
    }

    if (resampled_data)
        xfree(resampled_data);
    if (decoded_data)
        xfree(decoded_data);
}
Exemple #3
0
static int
alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels)
{	static	int epipe_count = 0 ;

	int total = 0 ;
	int retval ;

	if (epipe_count > 0)
		epipe_count -- ;

	while (total < frames)
	{	retval = snd_pcm_writei (alsa_dev, data + total * channels, frames - total) ;

		if (retval >= 0)
		{	total += retval ;
			if (total == frames)
				return total ;

			continue ;
			} ;

		switch (retval)
		{	case -EAGAIN :
					puts ("alsa_write_float: EAGAIN") ;
					continue ;
					break ;

			case -EPIPE :
					if (epipe_count > 0)
					{	printf ("alsa_write_float: EPIPE %d\n", epipe_count) ;
						if (epipe_count > 140)
							return retval ;
						} ;
					epipe_count += 100 ;

#if 0
					if (0)
					{	snd_pcm_status_t *status ;

						snd_pcm_status_alloca (&status) ;
						if ((retval = snd_pcm_status (alsa_dev, status)) < 0)
							fprintf (stderr, "alsa_out: xrun. can't determine length\n") ;
						else if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN)
						{	struct timeval now, diff, tstamp ;

							gettimeofday (&now, 0) ;
							snd_pcm_status_get_trigger_tstamp (status, &tstamp) ;
							timersub (&now, &tstamp, &diff) ;

							fprintf (stderr, "alsa_write_float xrun: of at least %.3f msecs. resetting stream\n",
									diff.tv_sec * 1000 + diff.tv_usec / 1000.0) ;
							}
						else
							fprintf (stderr, "alsa_write_float: xrun. can't determine length\n") ;
						} ;
#endif

					snd_pcm_prepare (alsa_dev) ;
					break ;

			case -EBADFD :
					fprintf (stderr, "alsa_write_float: Bad PCM state.n") ;
					return 0 ;
					break ;

			case -ESTRPIPE :
					fprintf (stderr, "alsa_write_float: Suspend event.n") ;
					return 0 ;
					break ;

			case -EIO :
					puts ("alsa_write_float: EIO") ;
					return 0 ;

			default :
					fprintf (stderr, "alsa_write_float: retval = %d\n", retval) ;
					return 0 ;
					break ;
			} ; /* switch */
		} ; /* while */

	return total ;
} /* alsa_write_float */
Exemple #4
0
void *audiothread(void *v) {
    int						policy;
    sched_param		sched;
    int						err;
    alsaaudio 		*dev;

    pthread_getschedparam(pthread_self(),&policy,&sched);
    sched.sched_priority++;//policy=SCHED_RR;
    pthread_setschedparam(pthread_self(),policy,&sched);
    dev=(alsaaudio*)v;

    unsigned int val;
    snd_pcm_t *fd;
    snd_pcm_uframes_t periodsize;
    snd_pcm_hw_params_t *hwparams;
    snd_pcm_hw_params_alloca(&hwparams);
    int output_rate;
    int channels;
    int fragment_size;
    int fragment_count;

    err=snd_pcm_open(&fd, strdup("default"), SND_PCM_STREAM_PLAYBACK, 0);
    if (err<0) return -1;

    fragment_size=LINUXFRAG;  //overall buffer size
    fragment_count=2; //2 - 16 fragment count - 2 minimum, the lower it is potentially the lower the latency

//configure device
    if (snd_pcm_hw_params_any(fd, hwparams) < 0) {
        //printf("linuxaudio failed at params any\n");
        return -1;
    }
    if (snd_pcm_hw_params_set_access(fd, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
        //printf("linuxaudio failed at set access\n");
        return -1;
    }

    if (snd_pcm_hw_params_set_format(fd, hwparams,SND_PCM_FORMAT_S16_LE) < 0) {
        //printf("linuxaudio failed at set format\n");
        return -1;
    }
    val = 44100;
    if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) {
        // Try 48KHZ too
        //printf("linuxaudio - %d HZ not available, trying 48000HZ\n", output_rate);
        val = 48000;
        if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) {
            //printf("linuxaudio failed at setting output rate (%d)\n", output_rate);
            return -1;
        }
        dev->mix->freq=val;
    }
    channels=2;
    if (snd_pcm_hw_params_set_channels(fd, hwparams, channels) < 0) {
        //printf("linuxaudio failed at set channels (%d)\n", channels);
        return -1;
    }
    periodsize = (fragment_size) / 4; // bytes -> frames for 16-bit,stereo - should be a minimum of 512
    if (snd_pcm_hw_params_set_period_size_near(fd, hwparams,&periodsize, 0) < 0) {
        //printf("linuxaudio failed at set period size (%d)\n", (int)periodsize);
        return -1;
    }
    val = fragment_count;
    if (snd_pcm_hw_params_set_periods_near(fd, hwparams,&val, 0) < 0) {
        //printf("linuxaudio failed at set periods (%d)\n", val);
        //should attempt a one by one period increase up to 16?
        return -1;
    }
    if (snd_pcm_hw_params(fd, hwparams) < 0) {
        //printf("linuxaudio failed at installing hw params\n");
        return -1;
    }
    //loop while playing sound
    dev->playing=1;
    while (dev->playing)
    {
        dev->mix->mix16(dev->buffer);
        if ((snd_pcm_writei (fd, dev->buffer,LINUXFRAG/2)) < 0) {	//Half buffer for two channels?
            //printf ("linuxaudio warning: buffer underrun occurred\n");
            if (snd_pcm_prepare(fd) < 0) {
                //printf ("linuxaudio failed at preparing pcm\n");
                dev->playing=0; //die gracefully
            }
        }
    }
    snd_pcm_drop(fd);
    snd_pcm_close (fd);
    return 0;
}
Exemple #5
0
void play(int sec, int freq, char *file)
{
	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;
	int fd;

	/* Check ranges */
	if (sec < 1 || sec > 4000) {
		printf("WARNING: Incorrect time to play range [1,4000] s\n");
		printf("\tSetting time to play to 5s...\n");
		sec = 5;
	}
	if (freq < 1000 || freq > 100000) {
		printf("ERROR: Incorrect frequency range [1000,100000] Hz\n");
		printf("\tSetting frequency to 44.1 kHz...\n");
		freq = 44100;
	}

	/* Open file */
	fd = open(file, O_RDONLY);
	if (fd < 0) {
		/* There was an error opening the file */
		printf("ERROR: Couldn't open file to play\n");
		printf("\tPlease make sure file exists\n");
	} else {
		/* Print that the file is playing with its parameters */
		printf("Playing file %s for %d seconds", file, sec);
		printf(" and frequency %d...\n", freq);

		/* Open PCM device for playback */
		rc = snd_pcm_open(&handle, "default", 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 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);
		/* freq bits/second sampling rate (CD quality) */
		val = freq;
		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 sec seconds */
		snd_pcm_hw_params_get_period_time(params, &val, &dir);
		/* sec seconds in microseconds divided by period time */
		loops = sec*1000000 / val;

		while (loops > 0) {
			loops--;
			rc = read(fd, 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);
			}
		}
		/*Close handle and free buffer*/
		snd_pcm_drain(handle);
		snd_pcm_close(handle);
		free(buffer);
	}
}
Exemple #6
0
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, "default",
                    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;
}
Exemple #7
0
void
ags_devout_alsa_play(AgsDevout *devout,
		     GError **error)
{    
  /*  */
  if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
    memset(devout->buffer[3], 0, (size_t) devout->dsp_channels * devout->buffer_size * sizeof(signed short));
      
    devout->out.alsa.rc = snd_pcm_writei(devout->out.alsa.handle,
					 devout->buffer[0],
					 (snd_pcm_uframes_t) (devout->buffer_size));

    if((AGS_DEVOUT_NONBLOCKING & (devout->flags)) == 0){
      if(devout->out.alsa.rc == -EPIPE){
	/* EPIPE means underrun */
	snd_pcm_prepare(devout->out.alsa.handle);

#ifdef AGS_DEBUG
	g_message("underrun occurred\0");
#endif
      }else if(devout->out.alsa.rc == -ESTRPIPE){
	static const struct timespec idle = {
	  0,
	  4000,
	};

	int err;

	while((err = snd_pcm_resume(devout->out.alsa.handle)) == -EAGAIN)
	  nanosleep(&idle, NULL); /* wait until the suspend flag is released */
	if(err < 0){
	  err = snd_pcm_prepare(devout->out.alsa.handle);
	}
      }else if(devout->out.alsa.rc < 0){
	g_message("error from writei: %s\0", snd_strerror(devout->out.alsa.rc));
      }else if(devout->out.alsa.rc != (int) devout->buffer_size) {
	g_message("short write, write %d frames\0", devout->out.alsa.rc);
      }
    }      
    //      g_message("ags_devout_play 0\0");
  }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
    memset(devout->buffer[0], 0, (size_t) devout->dsp_channels * devout->buffer_size * sizeof(signed short));

    devout->out.alsa.rc = snd_pcm_writei(devout->out.alsa.handle,
					 devout->buffer[1],
					 (snd_pcm_uframes_t) (devout->buffer_size));
     
    if((AGS_DEVOUT_NONBLOCKING & (devout->flags)) == 0){
      if(devout->out.alsa.rc == -EPIPE){
	/* EPIPE means underrun */
	snd_pcm_prepare(devout->out.alsa.handle);

#ifdef AGS_DEBUG
	g_message("underrun occurred\0");
#endif
      }else if(devout->out.alsa.rc == -ESTRPIPE){
	static const struct timespec idle = {
	  0,
	  4000,
	};

	int err;	

	while((err = snd_pcm_resume(devout->out.alsa.handle)) == -EAGAIN)
	  nanosleep(&idle, NULL); /* wait until the suspend flag is released */
	if(err < 0){
	  err = snd_pcm_prepare(devout->out.alsa.handle);
	}
      }else if(devout->out.alsa.rc < 0){
	g_message("error from writei: %s\0", snd_strerror(devout->out.alsa.rc));
      }else if(devout->out.alsa.rc != (int) devout->buffer_size) {
	g_message("short write, write %d frames\0", devout->out.alsa.rc);
      }
    }      
    //      g_message("ags_devout_play 1\0");
  }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
    memset(devout->buffer[1], 0, (size_t) devout->dsp_channels * devout->buffer_size * sizeof(signed short));
      
    devout->out.alsa.rc = snd_pcm_writei(devout->out.alsa.handle,
					 devout->buffer[2],
					 (snd_pcm_uframes_t) (devout->buffer_size));

    if((AGS_DEVOUT_NONBLOCKING & (devout->flags)) == 0){
      if(devout->out.alsa.rc == -EPIPE){
	/* EPIPE means underrun */
	snd_pcm_prepare(devout->out.alsa.handle);

#ifdef AGS_DEBUG
	g_message("underrun occurred\0");
#endif
      }else if(devout->out.alsa.rc == -ESTRPIPE){
	static const struct timespec idle = {
	  0,
	  4000,
	};

	int err;

	while((err = snd_pcm_resume(devout->out.alsa.handle)) == -EAGAIN)
	  nanosleep(&idle, NULL); /* wait until the suspend flag is released */
	if(err < 0){
	  err = snd_pcm_prepare(devout->out.alsa.handle);
	}
      }else if(devout->out.alsa.rc < 0){
	g_message("error from writei: %s\0", snd_strerror(devout->out.alsa.rc));
      }else if(devout->out.alsa.rc != (int) devout->buffer_size) {
	g_message("short write, write %d frames\0", devout->out.alsa.rc);
      }
    }
    //      g_message("ags_devout_play 2\0");
  }else if((AGS_DEVOUT_BUFFER3 & devout->flags) != 0){
    memset(devout->buffer[2], 0, (size_t) devout->dsp_channels * devout->buffer_size * sizeof(signed short));
      
    devout->out.alsa.rc = snd_pcm_writei(devout->out.alsa.handle,
					 devout->buffer[3],
					 (snd_pcm_uframes_t) (devout->buffer_size));

    if((AGS_DEVOUT_NONBLOCKING & (devout->flags)) == 0){
      if(devout->out.alsa.rc == -EPIPE){
	snd_pcm_prepare(devout->out.alsa.handle);

#ifdef AGS_DEBUG
	g_message("underrun occurred\0");
#endif
      }else if(devout->out.alsa.rc == -ESTRPIPE){
	static const struct timespec idle = {
	  0,
	  4000,
	};

	int err;

	while((err = snd_pcm_resume(devout->out.alsa.handle)) == -EAGAIN)
	  nanosleep(&idle, NULL); /* wait until the suspend flag is released */
	if(err < 0){
	  err = snd_pcm_prepare(devout->out.alsa.handle);
	}
      }else if(devout->out.alsa.rc < 0){
	g_message("error from writei: %s\0", snd_strerror(devout->out.alsa.rc));
      }else if(devout->out.alsa.rc != (int) devout->buffer_size) {
	g_message("short write, write %d frames\0", devout->out.alsa.rc);
      }
    }
    //      g_message("ags_devout_play 3\0");
  }

  /* determine if attack should be switched */
  devout->delay_counter += 1; //AGS_DEVOUT_DEFAULT_JIFFIE

  ///TODO:JK: fix me
  if(devout->delay_counter >= AGS_DEVOUT_DEFAULT_DELAY){ //devout->delay[devout->tic_counter]
    /* tic */
    ags_devout_tic(devout);

    devout->tic_counter += 1;

    if(devout->tic_counter == AGS_NOTATION_TICS_PER_BEAT){
      devout->tic_counter = 0;
    }

    /* delay */
    devout->delay_counter = 0;
  } 

  /* switch buffer flags */
  ags_devout_switch_buffer_flag(devout);

  snd_pcm_prepare(devout->out.alsa.handle);
}
Exemple #8
0
static ssize_t alsa_write(void *data, const void *buf_, size_t size_)
{
   alsa_t *alsa = (alsa_t*)data;
   const uint8_t *buf = (const uint8_t*)buf_;

   bool eagain_retry         = true;
   snd_pcm_sframes_t written = 0;
   snd_pcm_sframes_t size    = snd_pcm_bytes_to_frames(alsa->pcm, size_);

   while (size)
   {
      if (!alsa->nonblock)
      {
         int rc = snd_pcm_wait(alsa->pcm, -1);
         if (rc == -EPIPE || rc == -ESTRPIPE || rc == -EINTR)
         {
            if (snd_pcm_recover(alsa->pcm, rc, 1) < 0)
            {
               RARCH_ERR("[ALSA]: (#1) Failed to recover from error (%s)\n",
                     snd_strerror(rc));
               return -1;
            }
            continue;
         }
      }

      snd_pcm_sframes_t frames = snd_pcm_writei(alsa->pcm, buf, size);

      if (frames == -EPIPE || frames == -EINTR || frames == -ESTRPIPE)
      {
         if (snd_pcm_recover(alsa->pcm, frames, 1) < 0)
         {
            RARCH_ERR("[ALSA]: (#2) Failed to recover from error (%s)\n",
                  snd_strerror(frames));
            return -1;
         }

         break;
      }
      else if (frames == -EAGAIN && !alsa->nonblock) // Definitely not supposed to happen.
      {
         RARCH_WARN("[ALSA]: poll() was signaled, but EAGAIN returned from write.\n"
               "Your ALSA driver might be subtly broken.\n");

         if (eagain_retry)
         {
            eagain_retry = false;
            continue;
         }
         else
            return written;
      }
      else if (frames == -EAGAIN) // Expected if we're running nonblock.
      {
         return written;
      }
      else if (frames < 0)
      {
         RARCH_ERR("[ALSA]: Unknown error occured (%s).\n", snd_strerror(frames));
         return -1;
      }

      written += frames;
      buf     += (frames << 1) * (alsa->has_float ? sizeof(float) : sizeof(int16_t));
      size    -= frames;
   }

   return written;
}
Exemple #9
0
int main(int ac, char** av)
{
  pcm_desc_t desc;
  pcm_handle_t ipcm;
  pcm_handle_t opcm;
  mod_handle_t mod;
  int err;
  cmdline_t cmd;
  size_t i;

  err = -1;

  if (get_cmdline(&cmd, ac - 1, av + 1)) goto on_error_0;

  pcm_init_desc(&desc);
  desc.flags |= PCM_FLAG_IN;
  if (cmd.flags & CMDLINE_FLAG(IPCM)) desc.name = cmd.ipcm;
  if (pcm_open(&ipcm, &desc)) goto on_error_0;

  pcm_init_desc(&desc);
  desc.flags |= PCM_FLAG_OUT;
  if (cmd.flags & CMDLINE_FLAG(OPCM)) desc.name = cmd.opcm;
  if (pcm_open(&opcm, &desc)) goto on_error_1;

  if (mod_open(&mod, 512)) goto on_error_2;

  if (pcm_start(&ipcm)) goto on_error_3;
  if (pcm_start(&opcm)) goto on_error_3;

  signal(SIGINT, on_sigint);

  for (i = 0; is_sigint == 0; i += 1)
  {
    size_t nsampl;
    size_t navail;
    size_t off;

    /* read ipcm */

    err = snd_pcm_wait(ipcm.pcm, -1);
    if (is_sigint) break ;
    if (err < 0) goto on_ipcm_xrun;

    navail = (size_t)snd_pcm_avail_update(ipcm.pcm);

    if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.nsampl - ipcm.wpos;
    else nsampl = ipcm.rpos - ipcm.wpos;
    if (nsampl > navail) nsampl = navail;

    off = ipcm.wpos * ipcm.scale;
    err = snd_pcm_readi(ipcm.pcm, ipcm.buf + off, nsampl);
    if (err < 0) goto on_ipcm_xrun;

    ipcm.wpos += (size_t)err;
    if (ipcm.wpos == ipcm.nsampl) ipcm.wpos = 0;

    /* apply modifier */

  redo_mod:
    if (ipcm.wpos >= ipcm.rpos) nsampl = ipcm.wpos - ipcm.rpos;
    else nsampl = ipcm.nsampl - ipcm.rpos + ipcm.wpos;

    if (cmd.flags & CMDLINE_FLAG(FILT))
    {
      const size_t n = mod_apply
	(&mod, ipcm.buf, ipcm.nsampl, ipcm.rpos, nsampl);
      nsampl = n;
    }

    if (nsampl == 0) continue ;

    if ((ipcm.rpos + nsampl) > ipcm.nsampl)
    {
      const size_t n = ipcm.nsampl - ipcm.rpos;
      off = ipcm.rpos * ipcm.scale;
      err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, n);
      if (err < 0) goto on_opcm_xrun;
      nsampl -= n;
      ipcm.rpos = 0;
    }

    off = ipcm.rpos * ipcm.scale;
    err = snd_pcm_writei(opcm.pcm, ipcm.buf + off, nsampl);
    if (err < 0) goto on_opcm_xrun;
    ipcm.rpos += nsampl;
    if (ipcm.rpos == ipcm.nsampl) ipcm.rpos = 0;

    goto redo_mod;

    continue ;

  on_ipcm_xrun:
    if (pcm_recover_xrun(&ipcm, err)) PERROR_GOTO("", on_error_2);
    continue ;

  on_opcm_xrun:
    if (pcm_recover_xrun(&opcm, err)) PERROR_GOTO("", on_error_2);
    continue ;
  }

  err = 0;

 on_error_3:
  mod_close(&mod);
 on_error_2:
  pcm_close(&opcm);
 on_error_1:
  pcm_close(&ipcm);
 on_error_0:
  return err;
}
Exemple #10
0
    /* return 0 on success */
int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
    int *choutdev, int rate, int blocksize)
{
    int err, inchans = 0, outchans = 0, subunitdir;
    char devname[512];
    snd_output_t* out;
    int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
    int nfrags, i, iodev, dev2;
    int wantinchans, wantoutchans, device;

    nfrags = sys_schedadvance * (float)rate / (1e6 * frag_size);
        /* save our belief as to ALSA's buffer size for later */
    alsa_buf_samps = nfrags * frag_size;
    alsa_nindev = alsa_noutdev = 0;
    alsa_jittermax = ALSA_DEFJITTERMAX;

    if (sys_verbose)
        post("audio buffer set to %d", (int)(0.001 * sys_schedadvance));

    for (iodev = 0; iodev < naudioindev; iodev++)
    {
        alsa_numbertoname(audioindev[iodev], devname, 512);
        err = snd_pcm_open(&alsa_indev[alsa_nindev].a_handle, devname,
            SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
        check_error(err, 0, "snd_pcm_open");
        if (err < 0)
            continue;
        alsa_indev[alsa_nindev].a_devno = audioindev[iodev];
        snd_pcm_nonblock(alsa_indev[alsa_nindev].a_handle, 1);
        if (sys_verbose)
            post("opened input device name %s", devname);
        alsa_nindev++;
    }
    for (iodev = 0; iodev < naudiooutdev; iodev++)
    {
        alsa_numbertoname(audiooutdev[iodev], devname, 512);
        err = snd_pcm_open(&alsa_outdev[alsa_noutdev].a_handle, devname,
            SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
        check_error(err, 1, "snd_pcm_open");
        if (err < 0)
            continue;
        alsa_outdev[alsa_noutdev].a_devno = audiooutdev[iodev];
        snd_pcm_nonblock(alsa_outdev[alsa_noutdev].a_handle, 1);
        alsa_noutdev++;
    }
    if (!alsa_nindev && !alsa_noutdev)
        goto blewit;

        /* If all the open devices support mmap_noninterleaved, let's call
        Wini's code in s_audio_alsamm.c */
    alsa_usemmap = 1;
    for (iodev = 0; iodev < alsa_nindev; iodev++)
        if (!alsaio_canmmap(&alsa_indev[iodev]))
            alsa_usemmap = 0;
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
        if (!alsaio_canmmap(&alsa_outdev[iodev]))
            alsa_usemmap = 0;
    if (alsa_usemmap)
    {
        post("using mmap audio interface");
        if (alsamm_open_audio(rate, blocksize))
            goto blewit;
        else return (0);
    }
    for (iodev = 0; iodev < alsa_nindev; iodev++)
    {
        int channels = chindev[iodev];
        if (alsaio_setup(&alsa_indev[iodev], 0, &channels, &rate,
            nfrags, frag_size) < 0)
                goto blewit;
        inchans += channels;
    }
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
    {
        int channels = choutdev[iodev];
        if (alsaio_setup(&alsa_outdev[iodev], 1, &channels, &rate,
            nfrags, frag_size) < 0)
                goto blewit;
        outchans += channels;
    }
    if (!inchans && !outchans)
        goto blewit;

    for (iodev = 0; iodev < alsa_nindev; iodev++)
        snd_pcm_prepare(alsa_indev[iodev].a_handle);
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
        snd_pcm_prepare(alsa_outdev[iodev].a_handle);

        /* if duplex we can link the channels so they start together */
    for (iodev = 0; iodev < alsa_nindev; iodev++)
        for (dev2 = 0; dev2 < alsa_noutdev; dev2++)
    {
        if (alsa_indev[iodev].a_devno == alsa_outdev[iodev].a_devno)
        {
            snd_pcm_link(alsa_indev[iodev].a_handle,
                alsa_outdev[iodev].a_handle);
        }
    }

        /* allocate the status variables */
    if (!alsa_status)
    {
        err = snd_pcm_status_malloc(&alsa_status);
        check_error(err, -1, "snd_pcm_status_malloc");
    }

        /* fill the buffer with silence and prime the output FIFOs.  This
        should automatically start the output devices. */
    memset(alsa_snd_buf, 0, alsa_snd_bufsize);

    if (outchans)
    {
        i = (frag_size * nfrags)/DEFDACBLKSIZE + 1;
        while (i--)
        {
            for (iodev = 0; iodev < alsa_noutdev; iodev++)
                snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
                    DEFDACBLKSIZE);
        }
    }
    if (inchans)
    {
            /* some of the ADC devices might already have been started by
            starting the outputs above, but others might still need it. */
        for (iodev = 0; iodev < alsa_nindev; iodev++)
            if (snd_pcm_state(alsa_indev[iodev].a_handle)
                != SND_PCM_STATE_RUNNING)
                    if ((err = snd_pcm_start(alsa_indev[iodev].a_handle)) < 0)
                        check_error(err, -1, "input start failed");
    }
    return (0);
blewit:
    STUFF->st_inchannels = 0;
    STUFF->st_outchannels = 0;
    alsa_close_audio();
    return (1);
}
Exemple #11
0
int alsa_send_dacs(void)
{
    static double timenow;
    double timelast;
    t_sample *fp, *fp1, *fp2;
    int i, j, k, err, iodev, result, ch, resync = 0;;
    int chansintogo, chansouttogo;
    unsigned int transfersize;

    if (alsa_usemmap)
        return (alsamm_send_dacs());

    if (!alsa_nindev && !alsa_noutdev)
        return (SENDDACS_NO);

    chansintogo = STUFF->st_inchannels;
    chansouttogo = STUFF->st_outchannels;
    transfersize = DEFDACBLKSIZE;

    timelast = timenow;
    timenow = sys_getrealtime();

#ifdef DEBUG_ALSA_XFER
    if (timenow - timelast > 0.050)
        post("long wait between calls: %d",
            (int)(1000 * (timenow - timelast))), fflush(stderr);
    callno++;
#endif


    for (iodev = 0; iodev < alsa_nindev; iodev++)
    {
        result = snd_pcm_state(alsa_indev[iodev].a_handle);
        if (result == SND_PCM_STATE_XRUN)
        {
            int res2 = snd_pcm_start(alsa_indev[iodev].a_handle);
            fprintf(stderr, "restart alsa input\n");
            if (res2 < 0)
                fprintf(stderr, "alsa xrun recovery apparently failed\n");
        }
        snd_pcm_status(alsa_indev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return (SENDDACS_NO);
    }
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
    {
        result = snd_pcm_state(alsa_outdev[iodev].a_handle);
        if (result == SND_PCM_STATE_XRUN)
        {
            int res2 = snd_pcm_start(alsa_outdev[iodev].a_handle);
            fprintf(stderr, "restart alsa output\n");
            if (res2 < 0)
                fprintf(stderr, "alsa xrun recovery apparently failed\n");
        }
        snd_pcm_status(alsa_outdev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return (SENDDACS_NO);
    }

#ifdef DEBUG_ALSA_XFER
    post("xfer %d", transfersize);
#endif
    /* do output */
    for (iodev = 0, fp1 = STUFF->st_soundout, ch = 0;
        iodev < alsa_noutdev; iodev++)
    {
        int thisdevchans = alsa_outdev[iodev].a_channels;
        int chans = (chansouttogo < thisdevchans ? chansouttogo : thisdevchans);
        chansouttogo -= chans;

        if (alsa_outdev[iodev].a_sampwidth == 4)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                float s1 = *fp2 * INT32_MAX;
                ((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1);
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample32 *)alsa_snd_buf)[j] = 0;
        }
        else if (alsa_outdev[iodev].a_sampwidth == 3)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                int s = *fp2 * 8388352.;
                if (s > 8388351)
                    s = 8388351;
                else if (s < -8388351)
                    s = -8388351;
#if BYTE_ORDER == LITTLE_ENDIAN
                ((char *)(alsa_snd_buf))[3*j] = (s & 255);
                ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
                ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
                fprintf(stderr, "big endian 24-bit not supported");
#endif
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((char *)(alsa_snd_buf))[3*j] =
                    ((char *)(alsa_snd_buf))[3*j+1] =
                    ((char *)(alsa_snd_buf))[3*j+2] = 0;
        }
        else        /* 16 bit samples */
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                int s = *fp2 * 32767.;
                if (s > 32767)
                    s = 32767;
                else if (s < -32767)
                    s = -32767;
                ((t_alsa_sample16 *)alsa_snd_buf)[j] = s;
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample16 *)alsa_snd_buf)[j] = 0;
        }
        result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
            transfersize);

        if (result != (int)transfersize)
        {
    #ifdef DEBUG_ALSA_XFER
            if (result >= 0 || errno == EAGAIN)
                post("ALSA: write returned %d of %d\n",
                        result, transfersize);
            else post("ALSA: write: %s\n",
                         snd_strerror(errno));
    #endif
            sys_log_error(ERR_DATALATE);
            if (result == -EPIPE)
            {
                result = snd_pcm_prepare(alsa_indev[iodev].a_handle);
                if (result < 0)
                    fprintf(stderr, "read reset error %d\n", result);
            }
            else fprintf(stderr, "read other error %d\n", result);
            resync = 1;
        }

        /* zero out the output buffer */
        memset(STUFF->st_soundout, 0, DEFDACBLKSIZE * sizeof(*STUFF->st_soundout) *
               STUFF->st_outchannels);
        if (sys_getrealtime() - timenow > 0.002)
        {
    #ifdef DEBUG_ALSA_XFER
            post("output %d took %d msec\n",
                    callno, (int)(1000 * (timenow - timelast))), fflush(stderr);
    #endif
            timenow = sys_getrealtime();
            sys_log_error(ERR_DACSLEPT);
        }
    }
Exemple #12
0
int alsa_play_play(alsa_play_t alsa_play, glc_audio_data_header_t *audio_hdr, char *data)
{
	snd_pcm_uframes_t frames, rem;
	snd_pcm_sframes_t ret = 0;
	unsigned int c;

	if (audio_hdr->id != alsa_play->id)
		return 0;

	if (!alsa_play->pcm) {
		glc_log(alsa_play->glc, GLC_ERROR, "alsa_play", "broken stream %d",
			 alsa_play->id);
		return EINVAL;
	}

	frames = snd_pcm_bytes_to_frames(alsa_play->pcm, audio_hdr->size);
	glc_utime_t time = glc_state_time(alsa_play->glc);
	glc_utime_t duration = ((glc_utime_t) 1000000000 * (glc_utime_t) frames) /
			       (glc_utime_t) alsa_play->rate;

	if (time + alsa_play->silence_threshold + duration < audio_hdr->time) {
		struct timespec ts = {
		.tv_sec = (audio_hdr->time - time - duration - alsa_play->silence_threshold)/1000000000,
		.tv_nsec = (audio_hdr->time - time - duration - alsa_play->silence_threshold)%1000000000 };
		nanosleep(&ts,NULL);
	}
	/*
	 * This condition determine what will be the initial audio packet.
	 * it is preferable to be ahead by < duration/2 than behind
	 * the video by > duration/2
	 */
	else if (time > audio_hdr->time + duration/2) {
		glc_log(alsa_play->glc, GLC_DEBUG, "alsa_play",
			"dropped packet. now %" PRId64 " ts %" PRId64,
			time, audio_hdr->time);
		return 0;
	}

	rem = frames;

	while (rem > 0) {
		/* alsa is horrible... */
		/*snd_pcm_wait(alsa_play->pcm, duration);*/

		if (alsa_play->flags & GLC_AUDIO_INTERLEAVED)
			ret = snd_pcm_writei(alsa_play->pcm,
					    &data[snd_pcm_frames_to_bytes(alsa_play->pcm, frames - rem)],
					    rem);
		else {
			for (c = 0; c < alsa_play->channels; c++)
				alsa_play->bufs[c] =
					&data[snd_pcm_samples_to_bytes(alsa_play->pcm, frames)
					      * c + snd_pcm_samples_to_bytes(alsa_play->pcm, frames - rem)];
			ret = snd_pcm_writen(alsa_play->pcm, alsa_play->bufs, rem);
		}

		if (ret == 0)
			break;

		if ((ret == -EBUSY) || (ret == -EAGAIN))
			break;
		else if (ret < 0) {
			if ((ret = alsa_play_xrun(alsa_play, ret))) {
				glc_log(alsa_play->glc, GLC_ERROR, "alsa_play",
					 "xrun recovery failed: %s", snd_strerror(-ret));
				return ret;
			}
		} else
			rem -= ret;
	}

	return 0;
}
void playback() {

    int err;
    unsigned int i;
    snd_pcm_t *handle;

//    for (i = 0; i < sizeof(buffer); i++)
//            buffer[i] = random() & 0xff;
    if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
            printf("Playback open error: %s\n", snd_strerror(err));
            exit(EXIT_FAILURE);
    }

    initialize(handle);

	  printBuffer(buffer, 0, 10);
//	    for (i = 0; i < sizeof(buffer); i++)
//	    	buffer[i] = random() & 0xff;
	for (i = 0; i < NUM_FRAMES; i++) {
		if ((err = snd_pcm_writei (handle, buffer+FRAME_SIZE*i*mult, FRAME_SIZE)) != FRAME_SIZE) {
		  fprintf (stderr, "write from audio interface failed (%s)\n",
				   err, snd_strerror (err));
		  exit (1);
		}
		fprintf(stdout, "write %d done\n", i);
		printBuffer(buffer, FRAME_SIZE*i*mult, 10);
	}
    snd_pcm_close(handle);

//    int err;
//           unsigned int i;
//           snd_pcm_t *handle;
//           snd_pcm_sframes_t frames;
//           for (i = 0; i < sizeof(buffer); i++)
//                   buffer[i] = random() & 0xff;
//           if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
//                   printf("Playback open error: %s\n", snd_strerror(err));
//                   exit(EXIT_FAILURE);
//           }
//           if ((err = snd_pcm_set_params(handle,
//                                         SND_PCM_FORMAT_U8,
//                                         SND_PCM_ACCESS_RW_INTERLEAVED,
//                                         1,
//                                         48000,
//                                         1,
//                                         500000)) < 0) {   /* 0.5sec */
//                   printf("Playback open error: %s\n", snd_strerror(err));
//                   exit(EXIT_FAILURE);
//           }
//           for (i = 0; i < 16; i++) {
//                   frames = snd_pcm_writei(handle, buffer, sizeof(buffer));
//                   if (frames < 0)
//                           frames = snd_pcm_recover(handle, frames, 0);
//                   if (frames < 0) {
//                           printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
//                           break;
//                   }
//                   if (frames > 0 && frames < (long)sizeof(buffer))
//                           printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames);
//           }
//           snd_pcm_close(handle);
}
/**
* @brief Playback AudioSample_t's pointed to by samples
*
* @param samples A pointer to AudioSample_t's to be played
* @param num_samples The number of samples pointed to by samples
*/
void AlsaPlayback::playAudio(const AudioSample_t *samples, const size_t num_samples)
{
	if(samples && (num_samples > 0) && alsa_handle)
	{
		bool error_cond = false;
		size_t frames_sent = 0;
		size_t pad_out = num_samples % AlsaPlayback::FRAME_PERIOD;
		size_t frames_to_send = num_samples + pad_out;

		AudioSample_t *send_samples = new AudioSample_t[frames_to_send];

		if(send_samples)
		{
			int rc = 0;

			memset(send_samples, 0, sizeof(AudioSample_t)*frames_to_send);
			memcpy(send_samples, samples, sizeof(AudioSample_t)*num_samples);

			for(frames_sent = 0, error_cond = false; (frames_sent < frames_to_send) && !error_cond; frames_sent += (size_t)frames)
			{
				if(0 != AlsaPlayback::_volume)
				{
					rc = snd_pcm_writei(alsa_handle, &(send_samples[frames_sent]), frames);

					if(-EPIPE == rc)
					{
						TRACE("playAudio() - underrun occurred in snd_pcm_writei()\n");
						snd_pcm_prepare(alsa_handle);
					}
					else if(-EBADFD == rc)
					{
						TRACE("playAudio() - PCM is not in the right state\n");
						AlsaPlayback::setupHandle();
					}
					else if (-ESTRPIPE == rc)
					{
						TRACE("playAudio() - stream is suspended, attempting recovery\n");
					}
					else if(rc < 0)
					{
						TRACEF("playAudio() - error occurred in snd_pcm_writei() [%d]\n", rc);
						error_cond = true;
					}
					else if(rc != (int)frames)
					{
						TRACE("playAudio() - short write occurred in snd_pcm_writei()\n");
					}
					else
					{
						_num_samples_played += rc;
					}
				}
			}

//			rc = snd_pcm_drain(alsa_handle);

			delete[] send_samples;
			send_samples = NULL;
		}
	}
}
Exemple #15
0
int record(int size,char *serverString)
{
	unsigned int pcm, tmp, dir;
	int rate, channels, seconds;
	snd_pcm_t *pcm_handle;
	snd_pcm_hw_params_t *params;
	snd_pcm_uframes_t frames;
	char *buff,*buf;
	int buff_size, loops;
	int fp; 
	/*if (argc < 4)
	{
		printf("Usage: %s <sample_rate> <channels> <seconds>\n",
				argv[0]);
		return -1;
	}*/

	rate = 8000;//atoi(argv[1]);
	channels = 1;//atoi(argv[2]);
	seconds = 10;//atoi(argv[3]);

	/* Open the PCM device in playback mode */
	if (pcm = snd_pcm_open(&pcm_handle, "default" ,	SND_PCM_STREAM_PLAYBACK, 0) < 0)
		printf("ERROR: Can't open \"%s\" PCM device. %s\n",	"default", snd_strerror(pcm));

	/* Allocate parameters object and fill it with default values*/
	snd_pcm_hw_params_alloca(&params);

	snd_pcm_hw_params_any(pcm_handle, params);

	/* Set parameters */
	if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
		printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

	if (pcm = snd_pcm_hw_params_set_format(pcm_handle, params,SND_PCM_FORMAT_U8) < 0)
		printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

	if (pcm = snd_pcm_hw_params_set_channels(pcm_handle, params, channels) < 0)
		printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

	if (pcm = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0) < 0)
		printf("ERROR: Can't set rate. %s\n", snd_strerror(pcm));

	/* Write parameters */
	if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0)
		printf("ERROR: Can't set harware parameters. %s\n", snd_strerror(pcm));

	/* Resume information */
	printf("PCM name: '%s'\n", snd_pcm_name(pcm_handle));

	printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(pcm_handle)));

	snd_pcm_hw_params_get_channels(params, &tmp);
	printf("channels: %i ", tmp);

	if (tmp == 1)
		printf("(mono)\n");
	else if (tmp == 2)
		printf("(stereo)\n");

	snd_pcm_hw_params_get_rate(params, &tmp, 0);
	printf("rate: %d bps\n", tmp);

	printf("seconds: %d\n", seconds);	

	/* Allocate buffer to hold single period */
	snd_pcm_hw_params_get_period_size(params, &frames, 0);

	buff_size = frames * channels * 2 /* 2 -> sample size */;
	buff = (char *) malloc(buff_size*3);

	size = frames * channels * 2 /* 2 -> sample size */;
	buf = (char *) realloc((void*)serverString,(size*3));
	
	snd_pcm_hw_params_get_period_time(params, &tmp, NULL);
	
	//fp=open("222.wav",O_RDONLY);
	for (loops = (seconds * 1000000) / tmp; loops > 0; loops--)
	{

		/*
		if (pcm = read(fp, buff, buff_size) == 0)
		{
			printf("Early end of file.\n");
			//return 0;
		}
		*/
		
		if (pcm = snd_pcm_writei(pcm_handle, buf, frames) == -EPIPE)
		{
			printf("XRUN.\n");

			snd_pcm_prepare(pcm_handle);
		} 
		else 
		if(pcm < 0) 
		{
			printf("ERROR. Can't write to PCM device. %s\n", snd_strerror(pcm));
		}
		
	}

	snd_pcm_drain(pcm_handle);
	snd_pcm_close(pcm_handle);
	free(buff);

	return 0;
}
Exemple #16
0
void* play_thread(void *argv)
{
    char *__file_name = argv;
    struct WAVE *_wave;

#ifdef SOLO
    _wave = (struct WAVE*)malloc(sizeof(struct WAVE));
    memset(&_wave, 0, sizeof(struct _wave));
    if(!wave_read_file(argv, &_wave )){
	goto ERR;
    }
#else
    if(!list_count){
	fprintf(stderr,"[PLAY]: Not such wav sound file.\nPlease call \'play_read_filelist(DIR_PATH)\'\n");
	exit(1);
    }
    for(_wave=head;;_wave=_wave->next){
	if(!strcmp(_wave->file_name, __file_name))break;
	if(head->prev == _wave){
	    fprintf(stderr,"[PLAY]: Invalid file_name...\n");
	    return NULL;
	}
    }
#endif
    if(DISP)
	fprintf(stderr,"[PLAY]: Player will be playing \"%s\".\n",__file_name);

    snd_pcm_t *handle;                  // handle for sound_device
    snd_pcm_hw_params_t *params;        // params for sound_device
    int result_func = 0;                // result for function return
    unsigned int sampling_rate = _wave->rate;   // sampling rate
    int dir;    // sub unit direction
    snd_pcm_uframes_t frames = 32;        // size of frame
    unsigned int buffer_size;                   // buffer_size for frame
    int16_t *frameBuffer=NULL;                       // buffer for frame
    unsigned int approximate_period;                     // period[us]

    {// open the pcm device
	// open pcm device
	result_func = snd_pcm_open(
		&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if ( result_func < 0 )
	{
	    fprintf(stderr,
		    "[PLAY]: unable to open pcm device :%s\n",
		    snd_strerror(result_func));
	    goto ERR;
	}
    }

    {// set parameter to device
	// allocate device params
	snd_pcm_hw_params_alloca(&params);
	// get default param
	snd_pcm_hw_params_any(handle, params);
	// set parameter Interleaved mode
	snd_pcm_hw_params_set_access(handle, params,
		SND_PCM_ACCESS_RW_INTERLEAVED);
	// set format parameter : monoral 1ch 16bit LittleEndian
	snd_pcm_hw_params_set_format(handle, params,
		SND_PCM_FORMAT_S16_LE);
	// set output_device parameter stereo 2ch
	snd_pcm_hw_params_set_channels(handle, params, _wave->channel);
	// approximates to a specified sampling rate
	// pcm	PCM handle
	// params	Configuration space
	// val	approximate target rate / returned approximate set rate
	// dir	Sub unit direction 
	snd_pcm_hw_params_set_rate_near(
		handle, params, &sampling_rate, &dir);
	// set parameter size of frame
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
	// set parameter to hardware_device
	result_func = snd_pcm_hw_params(handle, params);

	// err check
	if (result_func < 0) {
	    fprintf(stderr, "[PLAY]: unable to set hw parameters: %s\n",
		    snd_strerror(result_func));
	    goto ERR;
	}

	// get bufferSize / frame
	snd_pcm_hw_params_get_period_size(params, &frames, &dir);
	// calculate buffer_size
	buffer_size = frames * 2; /*????????? 48000,monoral ver */
	// allocate buffer
	frameBuffer = (int16_t *)malloc(buffer_size);
	memset(frameBuffer, 0, sizeof(*frameBuffer));

	// get playback period
	// params	Configuration space
	// val	Returned approximate period duration in us
	// dir	Sub unit direction 
	snd_pcm_hw_params_get_period_time(params, &approximate_period, &dir);
    }


    { // playback process
	// playback time
	unsigned int ptime = approximate_period * 2 * 10;

	// playback
	while ( ptime-- )
	{
	    result_func = fread(
		    frameBuffer, sizeof(unsigned char),
		    buffer_size, _wave->fp);

	    // data is ended
	    if ( result_func == 0 )
	    {
		//fprintf(stdout, "[PLAY]: end of input devce\n");
		break;
	    }

	    // buffer_size is not correct
	    if ( result_func != buffer_size )
	    {
		/*
		   fprintf(stderr,
		   "short read: read %d bytes\n", result_func);
		   */
		break;
	    }

	    // playback
	    result_func = snd_pcm_writei(
		    handle, frameBuffer, frames);
	}
    }

    // for unplayed frame,wait sound finish
    snd_pcm_drain(handle);
    if(DISP)
	fprintf(stderr,"[PLAY]: Finished playing %s.\n",__file_name);

ERR :
    { // release
	if ( frameBuffer != NULL ){ free(frameBuffer); }
	if ( handle != NULL ) { snd_pcm_close(handle); }
    }
    return NULL;
}
Exemple #17
0
int main(int argc, char **argv)
{
   char *outFile;
   char *inFile[1];
// FILE *fout;
   FILE *fin[1];
   /*Holds the audio that will be written to file (16 bits per sample)*/
   short out[FRAME_SIZE];

    //int i;
    int result, length, tot_len;

    /*保存编码的状态*/         
    static void *stateDecode; 
   /*保存字节因此他们可以被speex常规读写*/
    static SpeexBits bitsDecode;
   //模式寄存器
    static const SpeexMode *mode=NULL;
   //解码器的采样频率
    static int speexFrequency = SAMPLERATE; //编码器的采样率
   /*得到的缓冲区的大小*/  
    static spx_int32_t frame_size; 
   /*得到的缓冲区的大小*/
   //static int channe = CHANNELS;
    /*得到是立体声*/
    //static SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; //单声到 立体声

   /* 初始话IP端口结构*/
#if (SAMPLERATE == 8000)
    mode = speex_lib_get_mode (SPEEX_MODEID_NB); //宽带编码
#elif (SAMPLERATE == 16000)
    mode = speex_lib_get_mode (SPEEX_MODEID_WB); //宽带编码
#elif (SAMPLERATE == 32000)
    mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //宽带编码
#endif
    //mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //在宽带模式解码


    stateDecode = speex_decoder_init(mode);      //新建一个解码器 

    speex_encoder_ctl(stateDecode, SPEEX_GET_FRAME_SIZE, &frame_size); //得到缓冲区大小

    speex_decoder_ctl(stateDecode, SPEEX_SET_SAMPLING_RATE, &speexFrequency); //设置解码器的采样频率

    speex_bits_init(&bitsDecode); //初始解码器

   char cbits[200];
   int nbBytes;
   /*Holds the state of the decoder*/
   //void *state;
   /*Holds bits so they can be read and written to by the Speex routines*/
   //SpeexBits bits;
   int i, tmp;
   int rc;

   printf("%s: start\n", __func__);


#if (SOUND_INTERFACE == SOUND_OSS)
	  init_oss_play();
#elif (SOUND_INTERFACE == SOUND_ALSA)
	 init_alsa_play();
#endif
   /*Create a new decoder state in narrowband mode*/
   stateDecode = speex_decoder_init(&speex_uwb_mode);

   /*Set the perceptual enhancement on*/
   tmp=1;
   speex_decoder_ctl(stateDecode, SPEEX_SET_ENH, &tmp);
   //printf("%s: 22222222\n", __func__);
	 inFile[0]	= argv[1];
	 //inFile[1]	= argv[2];	 
//   outFile = argv[1];
   //fout = fopen(outFile, "w");
   fin[0] = fopen(inFile[0], "r");//打开输入的spx文件
   
   if(fin[0] ==NULL)
   {
     perror("打开文件错误");
     exit(1);
   }
   
   //printf("%s: 3333333\n", __func__);
   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bitsDecode);
   //printf("%s: 4444444\n", __func__);   
   while (1)
   {   //printf("%s: 55555\n", __func__);
      //printf("%s: 1111111\n", __func__);
speex_bits_reset(&bitsDecode); 
      /*Read the size encoded by sampleenc, this part will likely be 
        different in your application*/
      fread(&nbBytes, sizeof(int), 1, fin[0]);
      fprintf (stderr, "nbBytes: %d\n", nbBytes);
      if (feof(fin[0]))
         break;
         //printf("%s: 666\n", __func__);
      /*Read the "packet" encoded by sampleenc*/
      fread(cbits, 1, nbBytes, fin[0]);
      /*Copy the data into the bit-stream struct*/
      speex_bits_read_from(&bitsDecode, cbits, nbBytes);

      /*Decode the data*/
      speex_decode_int(stateDecode, &bitsDecode, out);
#if 0
      /*Copy from float to short (16 bits) for output*/
      for (i=0;i<FRAME_SIZE;i++)
         out[i]=output[i];
   //printf("%s: 88888\n", __func__);
      /*Write the decoded audio to file*/
      //fwrite(out, sizeof(short), FRAME_SIZE, fout);
#endif 


#if (SOUND_INTERFACE == SOUND_OSS)
      rc = write(fdsoundplay, out, (SAMPLERATE/1000*READMSFORONCE)*sizeof(short));
      if(rc != (SAMPLERATE/1000*READMSFORONCE)*sizeof(short))
      {
          printf("写入数据长度与预期不符合\n");
      }
#elif (SOUND_INTERFACE == SOUND_ALSA)
      rc = snd_pcm_writei(handle, out, (SAMPLERATE/1000*READMSFORONCE)); 
         //printf("%s: 99999\n", __func__);

            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));
                        
                rc = xrun_recovery(handle, rc);             
                if (rc < 0) 
                {
                    printf("Write error: %s\n", snd_strerror(rc));
                    //return -1;
                }                   
            }  
            else if (rc != (int)(SAMPLERATE/1000*READMSFORONCE)) 
            {
                fprintf(stderr, "short write, write %d frames\n", rc);
            }
#endif
   }
   
printf("end\n");
   /*Destroy the decoder state*/
   speex_decoder_destroy(stateDecode);
   /*Destroy the bit-stream truct*/
   speex_bits_destroy(&bitsDecode);
   fclose(fin[0]);
   return 0;
}
Exemple #18
0
//经过优化的播放函数
void Player::play(char* data, size_t count_bytes) {
    size_t chunk_bytes;
    int rc;
	size_t count_frames, chunk_size;
	size_t bits_per_sample, bits_per_frame, bytes_per_frame;

	bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
	bits_per_frame = bits_per_sample * channels;
	bytes_per_frame = bits_per_frame >>3;
	chunk_size = this->m_frames;
	count_frames = count_bytes / bytes_per_frame; 

	//修改了size的赋值语句
    chunk_bytes = chunk_size * bytes_per_frame; /* 2 bytes/sample,  channels */
#ifdef DEBUG
	printf("bits per sample = %d\n", bits_per_sample);
	printf("bits per frame = %d\n", bits_per_frame);
	printf("chunk size = %d\n", chunk_size);
	printf("chunk bytes = %d\n", chunk_bytes);
	printf("sizeof data = %d\n", strlen(data));
	printf("count = %d\n", count_frames);
#endif

	if(count_frames < chunk_size){
		snd_pcm_format_set_silence(SND_PCM_FORMAT_S16_LE, data + count_frames * bytes_per_frame, (chunk_size - count_frames) * channels);
		count_frames = chunk_size;
	}

	while(count_frames > 0){

#ifdef ALSA_OPT
		usleep(5000);
#endif

        rc = snd_pcm_writei(this->m_pHandle, data, count_frames);
		if(rc == -EAGAIN ||(rc >0 && (size_t)rc < count_frames)){
			rc = snd_pcm_wait(this->m_pHandle, 1000);
		}
		else if (rc == -EPIPE) {
            /* EPIPE means underrun */
            fprintf(stderr, "xrun occurred: %s\n", strerror(rc));
            rc = snd_pcm_prepare(this->m_pHandle);
			if(rc < 0){
				fprintf(stderr, "prepare failed: %s\n", strerror(rc));
				return;
			}
        } 
        else if (rc == -ESTRPIPE) {
			fprintf(stderr, "suspended. Trying resume\n");
			while((rc = snd_pcm_resume(this->m_pHandle)) == -EAGAIN)
			  sleep(1);
			if(rc < 0){
				fprintf(stderr, "resume failed. Restart stream\n");
				if((rc = snd_pcm_prepare(this->m_pHandle)) < 0){
					fprintf(stderr, "suspend: prepare error: %s", strerror(rc));
					return;
				}
			}
		}
		else if (rc < 0){
			fprintf(stderr, "write error: %s\n", strerror(rc));
			return;
		}

		if(rc > 0){
#ifdef DEBUG
			printf("write %d frames\n", rc);
#endif
			count_frames -= rc;
			data += rc * bytes_per_frame;
		}
    }
}
Exemple #19
0
main (int argc, char *argv[])
{
    int i;
    int err;
    short buf[128];
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    int dir = 0;

    unsigned int rate = 16000;
    unsigned int channels = 1;

    if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        fprintf (stderr, "cannot open audio device %s (%s)\n",
             argv[1],
             snd_strerror (err));
        exit (1);
    }

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

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

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

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

    if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, &rate, &dir)) < 0) {
        fprintf (stderr, "cannot set sample rate (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, channels )) < 0) {
        fprintf (stderr, "cannot set channel count (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
        fprintf (stderr, "cannot set parameters (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    snd_pcm_hw_params_free (hw_params);

    if ((err = snd_pcm_prepare (playback_handle)) < 0) {
        fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
             snd_strerror (err));
        exit (1);
    }

    for (i = 0; i < 10; ++i) {
        if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) {
            fprintf (stderr, "write to audio interface failed (%s)\n",
                 snd_strerror (err));
            exit (1);
        }
    }

    snd_pcm_close (playback_handle);
    exit (0);
}
Exemple #20
0
/********************************************************
 *  playstereo                                          *
 *                                                      *
 * returns: 1 on successful play                        *
 *          -1 when soundfile does not play             *
 *          0 when soundfile plays with under.over run  *
 *******************************************************/
int playstereo(char *sfname1, char *sfname2, double breakpoint, double targlength, int targloc, int cueinterval, double period)
{
  
  SNDFILE *sf1, *sf2;
  SF_INFO *sfinfo1, *sfinfo2,*sfout_info;
  short *obuff, *obuff1, *obuff2;
  sf_count_t incount1, incount2;
  double padded;
  long pad = 0;
  int j= 0, loops = 0, cueframes, targframes, pauseframes, inframes, nspeak = 2, err, init;
  snd_pcm_uframes_t outframes, totframesout;
  unsigned short *ptr;
  int outsamprate = 44100;

  /* memory for SF_INFO structures */
  sfinfo1 = (SF_INFO *) malloc(sizeof(SF_INFO));
  sfinfo2 = (SF_INFO *) malloc(sizeof(SF_INFO));

  //fprintf(stderr, "trying to open '%s'\n", sfname); 
  /* open input files*/
  if(!(sf1 = sf_open(sfname1,SFM_READ,sfinfo1))){
    fprintf(stderr,"error opening input file %s\n",sfname1);
    return -1;
  }
  
  if(!(sf2 = sf_open(sfname2,SFM_READ,sfinfo2))){
    fprintf(stderr,"error opening input file %s\n",sfname2);
    return -1;
  }

  /* determine length inframes*/
  cueframes = (int) (breakpoint*outsamprate);
  pauseframes = (int) (cueinterval*outsamprate);
  targframes = (int) (targlength*outsamprate);
  inframes=(int)(cueframes+targframes);
  if(DEBUG){fprintf(stderr,"breakpoint:%g, cueframes:%i, pauseframes:%i targframes:%i, inframes:%i\n", breakpoint, cueframes, pauseframes, targframes, inframes);}
  /* allocate buffer memory */
  obuff1 = (short *) malloc(sizeof(int)*inframes);
  obuff2 = (short *) malloc(sizeof(int)*inframes);
  /* read the data */
  if(DEBUG){fprintf(stderr,"trying to sf_readf %d frames\n",(int)inframes);}
  incount1 = sf_readf_short(sf1, obuff1, inframes);
  if(DEBUG){fprintf(stderr,"got %d samples when I tried for %d from sf_readf_short()\n",(int)incount1, (int)inframes);}
  if(DEBUG){fprintf(stderr,"trying to sf_readf %d frames\n",(int)inframes);}
  incount2 = sf_readf_short(sf2, obuff2, inframes);
  if(DEBUG){fprintf(stderr,"got %d samples when I tried for %d from sf_readf_short()\n",(int)incount1, (int)inframes);}
  
  
  if (snd_pcm_prepare (handle) < 0) {
    fprintf (stderr, "cannot prepare audio interface for use\n");
    sf_close(sf1);
    free(sfinfo1);
    free(obuff1);
    sf_close(sf2);
    free(sfinfo2);
    free(obuff2);
    return -1;
  }
  if (snd_pcm_reset(handle)<0){
    fprintf (stderr, "cannot reset audio interface for use\n");
    return -1;
  }
  /* pad the file size up to next highest period count*/    
  pad = (period * ceil((nspeak*(inframes+pauseframes))/ period))-(nspeak*(inframes+pauseframes));
  padded = (nspeak*inframes)+pad;
  outframes = padded;
  
  obuff = (short *) malloc(sizeof(int)*outframes);
  if(DEBUG){fprintf(stderr,"outframes:%d, nspeak:%d, padded:%g, targloc:%i, cut: %i\n", (int)outframes, nspeak, padded, targloc,(int)(nspeak*cueframes));}
  /* combine individual buffers into obuff */
  loops=0;
  for (j=0; j<outframes; j=j+nspeak){
    loops++;
    if (j<(nspeak*cueframes)){
      obuff[j] = obuff1[j/nspeak];
      obuff[j+1] = obuff1[j/nspeak];
    }
    else if ((j >= (nspeak*cueframes)) & (j < (nspeak*(cueframes+pauseframes)))){
      obuff[j] = 0;
      obuff[j+1] = 0;
    }
    else if ((j >= (nspeak*(cueframes+pauseframes)))&(targloc == 1)){  /*MAKE SURE THIS CORRESPONDS TO RIGHT SPEAKER TARGET - should work if rt spk is set to channel 1*/
      obuff[j] = obuff1[j/nspeak-pauseframes];
      obuff[j+1] = obuff2[j/nspeak-pauseframes];
    }
    else if ((j>= (nspeak*(cueframes+pauseframes)))&(targloc == 2)){  /*MAKE SURE THIS CORRESPONDS TO LEFT  SPEAKER TARGET*/
      obuff[j] = obuff2[j/nspeak-pauseframes];
      obuff[j+1] = obuff1[j/nspeak-pauseframes];
    }
    else{
      fprintf(stderr,"ERROR: incompatable target location %i\n",targloc);
      return -1;
    }
  }
  sfout_info = (SF_INFO *) malloc(sizeof(SF_INFO));
  sfout_info->channels = nspeak;
  sfout_info->samplerate = 44100;
  sfout_info->format = sfinfo1->format;
  if(DEBUG){fprintf(stderr,"output file format:%x \tchannels: %d \tsamplerate: %d\n",sfout_info->format, sfout_info->channels, sfout_info->samplerate);}

  ptr = obuff;
  totframesout = 0;
  if(DEBUG){printf("outframes is now %d\n", (int) outframes);}
  /*start the actual playback*/
  while (outframes > 0) {
    err = snd_pcm_writei(handle,ptr, outframes);
    if (err < 0) {
      //init = 1;
      break;  /* skip one period */
    }
    if (snd_pcm_state(handle) == SND_PCM_STATE_RUNNING)
      //init = 0;

    totframesout += err;
    ptr += err * nspeak;
    outframes -= err;
    if(DEBUG){printf("outframes is now %d\n", (int) outframes);}
    if (outframes == 0){
      if(DEBUG){printf("outframes is zero so I'll break\n");}
      break;
    }
    /* it is possible, that the initial buffer cannot store */
    /* all data from the last period, so wait a while */
  }
  if(DEBUG==3){
    printf("exited while writei loop, so what am I waiting for?\n");
    printf("frames not played: %d \n", (int)outframes);
    printf("frames played: %d \n", (int) totframesout);
  }

  
 /*free up resources*/
  free(sfinfo1);free(sfinfo2);free(sfout_info);
  free(obuff);free(obuff1);free(obuff2);
  return 1;
 }
Exemple #21
0
static void *sound_play(void *args)
{
    char path[256];
    int samplerate;
    int err;
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    FILE *fp;

    db_msg("prepare play sound...\n");
    if (script_fetch("hdmi", "sound_file", (int *)path, sizeof(path) / 4)) {
        db_warn("unknown sound file, use default\n");
        strcpy(path, "/dragonboard/data/test48000.pcm");
    }
    if (script_fetch("hdmi", "samplerate", &samplerate, 1)) {
        db_warn("unknown samplerate, use default #48000\n");
        samplerate = 48000;
    }
    db_msg("samplerate #%d\n", samplerate);

    err = snd_pcm_open(&playback_handle, "hw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
    if (err < 0) {
        db_error("cannot open audio device (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_malloc(&hw_params);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_any(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, samplerate, 0);
    if (err < 0) {
        db_error("cannot set sample rate (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    if (err < 0) {
        db_error("cannot set channel count (%s), err = %d\n", snd_strerror(err), err);
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot set parameters (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    snd_pcm_hw_params_free(hw_params);

    db_msg("open test pcm file: %s\n", path);
    fp = fopen(path, "r");
    if (fp == NULL) {
        db_error("cannot open test pcm file(%s)\n", strerror(errno));
        pthread_exit((void *)-1);
    }

    db_msg("play it...\n");
    while (1) {
        while (!feof(fp)) {
            if (sound_play_stop) {
                goto out;
            }

            err = fread(buf, 1, BUF_LEN, fp);
            if (err < 0) {
                db_warn("read test pcm failed(%s)\n", strerror(errno));
            }

            err = snd_pcm_writei(playback_handle, buf, BUF_LEN/4);
            if (err < 0) {
                err = xrun_recovery(playback_handle, err);
                if (err < 0) {
                    db_warn("write error: %s\n", snd_strerror(err));
                }
            }

            if (err == -EBADFD) {
                db_warn("PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)\n");
            }
            if (err == -EPIPE) {
                db_warn("an underrun occurred\n");
            }
            if (err == -ESTRPIPE) {
                db_warn("a suspend event occurred (stream is suspended and waiting for an application recovery)\n");
            }

            if (feof(fp)) {
                fseek(fp, 0L, SEEK_SET);
            }
        }
    }

out:
    db_msg("play end...\n");
    fclose(fp);
    snd_pcm_close(playback_handle);
    pthread_exit(0);
}
Exemple #22
0
inline int AlsaAudioPlugin::update()
{
#if 0
    if(thread)
    {
        pthread_join(*thread, NULL);
        free(thread);
        thread = NULL;
    }
#endif

#if 0
    if(!thread)
    {
        pthread_mutex_lock(&mutex);
        param_thread.sndBuffer = sndBuffer;
        param_thread.sndBufferPtr = &sndBufferPtr;
        param_thread.qte = &qte;
        param_thread.pcm_handle = pcm_handle;
        pthread_mutex_unlock(&mutex);

        DebugLogMessage("Create pthread");
        thread = (pthread_t*)malloc(sizeof(pthread_t));
        pthread_create(thread, NULL, thread_snd_pcm_writei, (void*)&param_thread);
    }

    pthread_mutex_lock(&mutex_qte);

//    if(sndBufferPtr < (sndBuffer + periodsize + 4))
    {
        sndBufferPtr += 1*4;
        qte += 1;
    }

    pthread_mutex_unlock(&mutex_qte);

    return 0;
#else
	const int nb = 1;
    sndBufferPtr += (nb*4);
    qte += nb;

    int max_frames = periodsize; // >> 2;
    int frames = max_frames;

    while(qte >= max_frames)
    {
        //DebugLogMessage("1 qte: %d, frames: %d, sndBuffer %d, sndBufferPtr %d, periodsize %d", qte, frames, sndBuffer, sndBufferPtr, periodsize);
        int pcm_return;
        pcm_return = snd_pcm_writei(pcm_handle, sndBuffer, frames);
        if(pcm_return < frames)
        {
            if(pcm_return == -EPIPE)
            {
				int err;
                if(err = snd_pcm_prepare(pcm_handle) < 0)
				{
					DebugLogMessage("Cant recover underrun (%s)", snd_strerror(err));
				}
				else
				{
					DebugLogMessage("Underrun (%s) %d", snd_strerror(pcm_return), frames);
				}
            }
			else if(pcm_return < 0)
			{
				DebugLogMessage("Sound Error (%s)", snd_strerror(pcm_return));
			}
        }
        //DebugLogMessage("2 qte: %d, frames: %d, sndBuffer %d, sndBufferPtr %d, periodsize %d", qte, frames, sndBuffer, sndBufferPtr, periodsize);
        qte -= frames;
        sndBufferPtr -= 1*frames*4;
        //DebugLogMessage("2 qte: %d, frames: %d, sndBuffer %d, sndBufferPtr %d, periodsize %d", qte, frames, sndBuffer, sndBufferPtr, periodsize);
        if(sndBufferPtr < sndBuffer) sndBufferPtr = sndBuffer;
    }
    return 0;
#endif

    int pcm_return;
    while((pcm_return = snd_pcm_writei(pcm_handle, sndBuffer, 32)) < 0) {
        snd_pcm_prepare(pcm_handle);
        DebugLogMessage("Underrun %d", pcm_return);
        return 0;
    }
    return 0;
//    return 0;
//  while((pcmreturn = snd_pcm_writei(pcm_handle, sndBuffer, 1)) < 0) {
//      snd_pcm_prepare(pcm_handle);
//      ErrorLogMessage("Buffer Underrun");
//      return 0;
//  }
}
Exemple #23
0
static BOOL tsmf_alsa_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size)
{
	int len;
	int error;
	int frames;
	BYTE *end;
	BYTE *src;
	BYTE *pindex;
	int rbytes_per_frame;
	int sbytes_per_frame;
	TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
	DEBUG_TSMF("data_size %d", data_size);
	if(alsa->out_handle)
	{
		sbytes_per_frame = alsa->source_channels * alsa->bytes_per_sample;
		rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_sample;
		if((alsa->source_rate == alsa->actual_rate) &&
				(alsa->source_channels == alsa->actual_channels))
		{
			src = data;
		}
		else
		{
			alsa->dsp_context->resample(alsa->dsp_context, data, alsa->bytes_per_sample,
										alsa->source_channels, alsa->source_rate, data_size / sbytes_per_frame,
										alsa->actual_channels, alsa->actual_rate);
			frames = alsa->dsp_context->resampled_frames;
			DEBUG_TSMF("resampled %d frames at %d to %d frames at %d",
					   data_size / sbytes_per_frame, alsa->source_rate, frames, alsa->actual_rate);
			data_size = frames * rbytes_per_frame;
			src = alsa->dsp_context->resampled_buffer;
		}
		pindex = src;
		end = pindex + data_size;
		while(pindex < end)
		{
			len = end - pindex;
			frames = len / rbytes_per_frame;
			error = snd_pcm_writei(alsa->out_handle, pindex, frames);
			if(error == -EPIPE)
			{
				snd_pcm_recover(alsa->out_handle, error, 0);
				error = 0;
			}
			else if(error < 0)
			{
				DEBUG_TSMF("error len %d", error);
				snd_pcm_close(alsa->out_handle);
				alsa->out_handle = 0;
				tsmf_alsa_open_device(alsa);
				break;
			}
			DEBUG_TSMF("%d frames played.", error);
			if(error == 0)
				break;
			pindex += error * rbytes_per_frame;
		}
	}
	free(data);
	return TRUE;
}
snd_pcm_sframes_t snd_pcm_generic_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
{
	snd_pcm_generic_t *generic = pcm->private_data;
	return snd_pcm_writei(generic->slave, buffer, size);
}
/*----------------------------------------------------------------------
|    AlsaOutput_Write
+---------------------------------------------------------------------*/
static BLT_Result
AlsaOutput_Write(AlsaOutput* self, void* buffer, BLT_Size size)
{
    int          watchdog = 5;
    int          io_result;
    unsigned int sample_count;
    unsigned int sample_size;
    BLT_Result   result;

    /* ensure that the device is prepared */
    result = AlsaOutput_Prepare(self);
    if (BLT_FAILED(result)) return result;

    /* compute the number of samples */
    sample_size  = self->media_type.channel_count*self->media_type.bits_per_sample/8;
    sample_count = size / sample_size;
                           
    /* write samples to the device and handle underruns */       
    do {
        while (sample_count) {
            io_result = snd_pcm_writei(self->device_handle, 
                                       buffer, sample_count);
            if (io_result > 0) {
                buffer = (void*)((char*)buffer + io_result*sample_size);
                if ((unsigned int)io_result <= sample_count) {
                    sample_count -= io_result;
                } else {
                    /* strange, snd_pcm_writei returned more than we wrote */
                    sample_count = 0;
                }
            } else {
                break;
            }
        }        
        if (sample_count == 0) return BLT_SUCCESS;

        /* we reach this point if the first write failed */
        if (io_result < 0) {
            snd_pcm_status_t* status;
            snd_pcm_state_t   state;
            snd_pcm_status_alloca_no_assert(&status);

            io_result = snd_pcm_status(self->device_handle, status);
            if (io_result != 0) {
                return BLT_FAILURE;
            }
            state = snd_pcm_status_get_state(status);
            if (state == SND_PCM_STATE_XRUN) {
                ATX_LOG_FINE("**** UNDERRUN *****");
            
                /* re-prepare the channel */
                io_result = snd_pcm_prepare(self->device_handle);
                if (io_result != 0) {
                    return BLT_FAILURE;
                }
            } else {
               ATX_LOG_WARNING_1("**** STATE = %d ****", state);
            }
        } else {
            ATX_LOG_WARNING_1("snd_pcm_writei() returned %d", io_result); 
        }
        
        ATX_LOG_FINE("**** RETRY *****");

    } while(watchdog--);

    ATX_LOG_SEVERE("**** THE WATCHDOG BIT US ****");
    return BLT_FAILURE;
}
Exemple #26
0
static enum stream_state
alsa_refill_stream(cubeb_stream * stm)
{
  int r;
  unsigned short revents;
  snd_pcm_sframes_t avail;
  long got;
  void * p;
  int draining;

  draining = 0;

  pthread_mutex_lock(&stm->mutex);

  r = snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents);
  if (r < 0 || revents != POLLOUT) {
    /* This should be a stream error; it makes no sense for poll(2) to wake
       for this stream and then have the stream report that it's not ready.
       Unfortunately, this does happen, so just bail out and try again. */
    pthread_mutex_unlock(&stm->mutex);
    return RUNNING;
  }

  avail = snd_pcm_avail_update(stm->pcm);
  if (avail == -EPIPE) {
    snd_pcm_recover(stm->pcm, avail, 1);
    avail = snd_pcm_avail_update(stm->pcm);
  }

  /* Failed to recover from an xrun, this stream must be broken. */
  if (avail < 0) {
    pthread_mutex_unlock(&stm->mutex);
    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
    return ERROR;
  }

  /* This should never happen. */
  if ((unsigned int) avail > stm->buffer_size) {
    avail = stm->buffer_size;
  }

  /* poll(2) claims this stream is active, so there should be some space
     available to write.  If avail is still zero here, the stream must be in
     a funky state, so recover and try again. */
  if (avail == 0) {
    snd_pcm_recover(stm->pcm, -EPIPE, 1);
    avail = snd_pcm_avail_update(stm->pcm);
    if (avail <= 0) {
      pthread_mutex_unlock(&stm->mutex);
      stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
      return ERROR;
    }
  }

  p = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, avail));
  assert(p);

  pthread_mutex_unlock(&stm->mutex);
  got = stm->data_callback(stm, stm->user_ptr, p, avail);
  pthread_mutex_lock(&stm->mutex);
  if (got < 0) {
    pthread_mutex_unlock(&stm->mutex);
    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
    return ERROR;
  }
  if (got > 0) {
    snd_pcm_sframes_t wrote = snd_pcm_writei(stm->pcm, p, got);
    if (wrote == -EPIPE) {
      snd_pcm_recover(stm->pcm, wrote, 1);
      wrote = snd_pcm_writei(stm->pcm, p, got);
    }
    assert(wrote >= 0 && wrote == got);
    stm->write_position += wrote;
    gettimeofday(&stm->last_activity, NULL);
  }
  if (got != avail) {
    long buffer_fill = stm->buffer_size - (avail - got);
    double buffer_time = (double) buffer_fill / stm->params.rate;

    /* Fill the remaining buffer with silence to guarantee one full period
       has been written. */
    snd_pcm_writei(stm->pcm, (char *) p + got, avail - got);

    set_timeout(&stm->drain_timeout, buffer_time * 1000);

    draining = 1;
  }

  free(p);
  pthread_mutex_unlock(&stm->mutex);
  return draining ? DRAINING : RUNNING;
}
Exemple #27
0
//*******************************************************************************
//*  audio_thread_fxn                                                          **
//*******************************************************************************
//*  Input Parameters:                                                         **
//*      void *envByRef    --  a pointer to an audio_thread_env structure      **
//*                            as defined in audio_thread.h                    **
//*                                                                            **
//*          envByRef.quit -- when quit != 0, thread will cleanup and exit     **
//*                                                                            **
//*  Return Value:                                                             **
//*      void *            --  AUDIO_THREAD_SUCCESS or AUDIO_THREAD_FAILURE as **
//*                            defined in audio_thread.h                       **
//*******************************************************************************
void *audio_thread_fxn( void *envByRef )
{

// Variables and definitions
// *************************

    // Thread parameters and return value
    audio_thread_env * envPtr = envByRef;                  // < see above >
    void             * status = AUDIO_THREAD_SUCCESS;      // < see above >
    // The levels of initialization for initMask

    #define     INPUT_ALSA_INITIALIZED      0x1
    #define     INPUT_BUFFER_ALLOCATED      0x2
    #define     OUTPUT_ALSA_INITIALIZED     0x4
    #define     OUTPUT_BUFFER_ALLOCATED     0x8

    unsigned  int   initMask =  0x0;	// Used to only cleanup items that were init'd

    // Input and output driver variables
    //FILE	* inputFile = NULL;		// Input file pointer (i.e. handle)
    snd_pcm_t	*pcm_output_handle;
    snd_pcm_t	*pcm_capture_handle;		// Handle for the PCM device
    snd_pcm_uframes_t exact_bufsize;		// bufsize is in frames.  Each frame is 4 bytes

    int   blksize = BLOCKSIZE;			// Raw input or output frame size in bytes
    char *outputBuffer = NULL;
    char *outputBuffer2 = NULL;			// Output buffer for driver to read from
	char *playingBuffer = NULL;
// Thread Create Phase -- secure and initialize resources
// ******************************************************

    // Setup audio input device
    // ************************
    // Open an ALSA device channel for audio input
    exact_bufsize = blksize/BYTESPERFRAME;

    if( audio_io_setup( &pcm_capture_handle, SOUND_DEVICE, SAMPLE_RATE, 
			SND_PCM_STREAM_CAPTURE, &exact_bufsize ) == AUDIO_FAILURE )
    {
        ERR( "Audio_input_setup failed in audio_thread_fxn\n\n" );
        status = AUDIO_THREAD_FAILURE;
        goto cleanup;
    }
    DBG( "exact_bufsize = %d\n", (int) exact_bufsize);

    // Record that input OSS device was opened in initialization bitmask
    initMask |= INPUT_ALSA_INITIALIZED;

    blksize = exact_bufsize*BYTESPERFRAME;

    // Initialize audio output device
    // ******************************
    // Initialize the output ALSA device
    DBG( "pcm_output_handle before audio_output_setup = %d\n", (int) pcm_output_handle);
    exact_bufsize = blksize/BYTESPERFRAME;
    DBG( "Requesting bufsize = %d\n", (int) exact_bufsize);
    if( audio_io_setup( &pcm_output_handle, OUT_SOUND_DEVICE, SAMPLE_RATE, 
			SND_PCM_STREAM_PLAYBACK, &exact_bufsize) == AUDIO_FAILURE )
    {
        ERR( "audio_output_setup failed in audio_thread_fxn\n" );
        status = AUDIO_THREAD_FAILURE;
        goto  cleanup ;
    }
	blksize = exact_bufsize;
	DBG( "pcm_output_handle after audio_output_setup = %d\n", (int) pcm_output_handle);
	DBG( "blksize = %d, exact_bufsize = %d\n", blksize, (int) exact_bufsize);

    // Record that input ALSA device was opened in initialization bitmask
    initMask |= OUTPUT_ALSA_INITIALIZED;

    // Create output buffer to write from into ALSA output device
    if( ( outputBuffer = malloc( blksize ) ) == NULL )
    {
        ERR( "Failed to allocate memory for output block (%d)\n", blksize );
        status = AUDIO_THREAD_FAILURE;
        goto  cleanup ;
    }
	// Create 5 seconds of output buffer to circularly update
    if( ( outputBuffer2 = malloc( 500*blksize ) ) == NULL )
    {
        ERR( "Failed to allocate memory for output block (%d)\n", blksize );
        status = AUDIO_THREAD_FAILURE;
        goto  cleanup ;
    }
	// This adds the two audio files together for play when enter is pressed
    if( ( playingBuffer = malloc( 500*blksize ) ) == NULL )
    {
        ERR( "Failed to allocate memory for output block (%d)\n", blksize );
        status = AUDIO_THREAD_FAILURE;
        goto  cleanup ;
    }

    DBG( "Allocated output audio buffer of size %d to address %p\n", blksize, outputBuffer );

    // Record that the output buffer was allocated in initialization bitmask
    initMask |= OUTPUT_BUFFER_ALLOCATED;


// Thread Execute Phase -- perform I/O and processing
// **************************************************
    // Get things started by sending some silent buffers out.
    int i;

    memset(outputBuffer, 0, blksize);		// Clear the buffer
    memset(outputBuffer2, 0, blksize);		// Clear the buffer
    memset(playingBuffer, 0, blksize);		// Clear the buffer
    for(i=0; i<4; i++) {
	snd_pcm_readi(pcm_capture_handle, outputBuffer, blksize/BYTESPERFRAME);
	if ((snd_pcm_writei(pcm_output_handle, outputBuffer,
		exact_bufsize)) < 0) {
	    snd_pcm_prepare(pcm_output_handle);
	    ERR( "<<<Pre Buffer Underrun >>> \n");
	      }
	}


//
// Processing loop
//
    DBG( "Entering audio_thread_fxn processing loop\n" );

    int count = 0;			//count for the specific audio frame being played
	int count2 = 0;			//count to 500 to keep track of circular loop
	int flag = 0;			//goes high to indicate that 500 frames are captured and ready to be played back
	int playaudiocheck = 1; //goes high to indicate that 500 frames have been played and are ready for capture and play again
    while( !envPtr->quit )
    {

        // Read capture buffer from ALSA input device

        if( snd_pcm_readi(pcm_capture_handle, outputBuffer, blksize/BYTESPERFRAME) < 0 )
        {
	    snd_pcm_prepare(pcm_capture_handle);
        }

        // Write output buffer into ALSA output device
		if(!audiocaller || !flag){
			//If not playing last five seconds of audio or the buffer isn't filled to the 5 second capacity, then we want to continue to play audio regularly
        	if (snd_pcm_writei(pcm_output_handle, outputBuffer, blksize/BYTESPERFRAME) < 0) {
            	snd_pcm_prepare(pcm_output_handle);
	    		// Send out an extra blank buffer if there is an underrun and try again.
	    memset(outputBuffer, 0, blksize);		// Clear the buffer
	    snd_pcm_writei(pcm_output_handle, outputBuffer, exact_bufsize);
      		}
		}

		//Now we want to check to see if the buffer is full and the audio needs to be played back as well as if the audio has finished playing back
		if(audiocaller && (count2 == 499) && playaudiocheck){
		// This will determine that we are playing audio from this point as well we will say not to come back into this loop until the audio has been played and set count2 back to 0 for playing from the beginning
			count2 = 0;
			flag = 1;
			playaudiocheck = 0;
		}

		//Now we will play audio only if the flag says that we have a full buffer
		if(audiocaller && flag){
		//We have to add the signals from what sound is currently happening to the sounds that happened over the last 5 seconds together and then have them playback byter for byte
		for(i=0; i < blksize; i++){
			playingBuffer[i] = outputBuffer2[(count2*blksize)+i] + outputBuffer[i];
		}
		
		//When the audio has been formed it them plays back through the speakers with a snd_pcm_writei call for playingBuffer
		if (snd_pcm_writei(pcm_output_handle, playingBuffer, blksize/BYTESPERFRAME) < 0){ 
		   	snd_pcm_prepare(pcm_output_handle);
		    // Send out an extra blank buffer if there is an underrun and try again.
	        memset(playingBuffer, 0, blksize);		// Clear the buffer
	        snd_pcm_writei(pcm_output_handle, playingBuffer, blksize/BYTESPERFRAME);
        }
		//We now need to detect whether or not the buffer has come to an end and if it has we need to let the program know that we don't want to continue playing both audios together as well as let the buffer know it can be recalled to play again
		if(count2 > 498){
			audiocaller = 0;
			playaudiocheck = 1;
			flag = 0;
		}

}
	//Copies the recorded audio into the new buffer at the specified index
	memcpy(outputBuffer2 + (count2*blksize), outputBuffer, blksize);
	count++;
	count2++;
	count2 = count2 % 500;

	//DBG("%d, ", count++);
    }
    DBG("\n");

    DBG( "Exited audio_thread_fxn processing loop\n" );


// Thread Delete Phase -- free up resources allocated by this file
// ***************************************************************

cleanup:

    DBG( "Starting audio thread cleanup to return resources to system\n" );


    // Close output ALSA device
    if( initMask & OUTPUT_ALSA_INITIALIZED )
        if( audio_io_cleanup( pcm_output_handle ) != AUDIO_SUCCESS )
        {
            ERR( "audio_output_cleanup() failed for file descriptor %d\n", (int)pcm_output_handle );
            status = AUDIO_THREAD_FAILURE;
        }

    // Free allocated buffers
    // **********************

    // Free output buffer
    if( initMask & OUTPUT_BUFFER_ALLOCATED )
    {
        free( outputBuffer );
		free( outputBuffer2 );
		free( playingBuffer );
        DBG( "Freed audio output buffer at location %p\n", outputBuffer );
    }

    // Return from audio_thread_fxn function
    // *************************************
	
    // Return the status at exit of the thread's execution
    DBG( "Audio thread cleanup complete. Exiting audio_thread_fxn\n" );
    return status;
}
Exemple #28
0
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int process (jack_nframes_t nframes, void *arg) {

    if (running_freewheel) {
	JSList *node = playback_ports;

	while ( node != NULL)
	{
	    jack_port_t *port = (jack_port_t *) node->data;
	    float *buf = jack_port_get_buffer (port, nframes);

	    memset(buf, 0, sizeof(float)*nframes);

	    node = jack_slist_next (node);
	}

	return 0;
    }

    int rlen;
    int err;
    snd_pcm_sframes_t delay = target_delay;
    int i;

    delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ;

    delay -= jack_frames_since_cycle_start( client );
    // Do it the hard way.
    // this is for compensating xruns etc...

    if( delay > (target_delay+max_diff) ) {
	snd_pcm_rewind( alsa_handle, delay - target_delay );
	output_new_delay = (int) delay;

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	// first look at the PI controller, this code is just a special case, which should never execute once
	// everything is swung in. 
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    if( delay < (target_delay-max_diff) ) {

	output_new_delay = (int) delay;

	while ((target_delay-delay) > 0) {
	    snd_pcm_uframes_t to_write = ((target_delay-delay) > 512) ? 512 : (target_delay-delay);
	    snd_pcm_writei( alsa_handle, tmpbuf, to_write );
	    delay += to_write;
	}

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    /* ok... now we should have target_delay +- max_diff on the alsa side.
     *
     * calculate the number of frames, we want to get.
     */

    double offset = delay - target_delay;

    // Save offset.
    offset_array[(offset_differential_index++)% smooth_size ] = offset;

    // Build the mean of the windowed offset array
    // basically fir lowpassing.
    double smooth_offset = 0.0;
    for( i=0; i<smooth_size; i++ )
	    smooth_offset +=
		    offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i];
    smooth_offset /= (double) smooth_size;

    // this is the integral of the smoothed_offset
    offset_integral += smooth_offset;

    // Clamp offset.
    // the smooth offset still contains unwanted noise
    // which would go straigth onto the resample coeff.
    // it only used in the P component and the I component is used for the fine tuning anyways.
    if( fabs( smooth_offset ) < pclamp )
	    smooth_offset = 0.0;

    // ok. now this is the PI controller. 
    // u(t) = K * ( e(t) + 1/T \int e(t') dt' )
    // K = 1/catch_factor and T = catch_factor2
    double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2;

    // now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
    current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean;

    // Output "instrumentatio" gonna change that to real instrumentation in a few.
    output_resampling_factor = (float) current_resample_factor;
    output_diff = (float) smooth_offset;
    output_integral = (float) offset_integral;
    output_offset = (float) offset;

    // Clamp a bit.
    if( current_resample_factor < resample_lower_limit ) current_resample_factor = resample_lower_limit;
    if( current_resample_factor > resample_upper_limit ) current_resample_factor = resample_upper_limit;

    // Now Calculate how many samples we need.
    rlen = ceil( ((double)nframes) * current_resample_factor )+2;
    assert( rlen > 2 );

    // Calculate resample_mean so we can init ourselves to saner values.
    resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
    /*
     * now this should do it...
     */

    outbuf = alloca( rlen * formats[format].sample_size * num_channels );

    resampbuf = alloca( rlen * sizeof( float ) );
    /*
     * render jack ports to the outbuf...
     */

    int chn = 0;
    JSList *node = playback_ports;
    JSList *src_node = playback_srcs;
    SRC_DATA src;

    while ( node != NULL)
    {
	jack_port_t *port = (jack_port_t *) node->data;
	float *buf = jack_port_get_buffer (port, nframes);

	SRC_STATE *src_state = src_node->data;

	src.data_in = buf;
	src.input_frames = nframes;

	src.data_out = resampbuf;
	src.output_frames = rlen;
	src.end_of_input = 0;

	src.src_ratio = current_resample_factor;

	src_process( src_state, &src );

	formats[format].jack_to_soundcard( outbuf + format[formats].sample_size * chn, resampbuf, src.output_frames_gen, num_channels*format[formats].sample_size, NULL);

	src_node = jack_slist_next (src_node);
	node = jack_slist_next (node);
	chn++;
    }

    // now write the output...
again:
  err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  //err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  if( err < 0 ) {
      printf( "err = %d\n", err );
      if (xrun_recovery(alsa_handle, err) < 0) {
	  printf("Write error: %s\n", snd_strerror(err));
	  exit(EXIT_FAILURE);
      }
      goto again;
  }

    return 0;      
}
Exemple #29
0
static void
laudio_alsa_write(uint8_t *buf, uint64_t rtptime)
{
  struct pcm_packet *pkt;
  snd_pcm_sframes_t nsamp;
  int ret;

  pkt = (struct pcm_packet *)malloc(sizeof(struct pcm_packet));
  if (!pkt)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Out of memory for PCM pkt\n");

      update_status(LAUDIO_FAILED);
      return;
    }

  memcpy(pkt->samples, buf, sizeof(pkt->samples));

  pkt->rtptime = rtptime;
  pkt->offset = 0;
  pkt->next = NULL;

  if (pcm_pkt_tail)
    {
      pcm_pkt_tail->next = pkt;
      pcm_pkt_tail = pkt;
    }
  else
    {
      pcm_pkt_head = pkt;
      pcm_pkt_tail = pkt;
    }

  if (pcm_pos < pcm_pkt_head->rtptime)
    {
      pcm_pos += AIRTUNES_V2_PACKET_SAMPLES;

      return;
    }
  else if ((pcm_status != LAUDIO_RUNNING) && (pcm_pos + pcm_buf_threshold >= pcm_start_pos))
    {
      /* Kill threshold */
      ret = laudio_alsa_set_start_threshold(0);
      if (ret < 0)
	DPRINTF(E_WARN, L_LAUDIO, "Couldn't set PCM start threshold to 0 for output start\n");

      update_status(LAUDIO_RUNNING);
    }

  pkt = pcm_pkt_head;

  while (pkt)
    {
      if (pcm_recovery)
	{
	  ret = laudio_alsa_xrun_recover(0);
	  if ((ret == 2) && (pcm_recovery < 10))
	    return;
	  else
	    {
	      if (ret == 2)
		DPRINTF(E_LOG, L_LAUDIO, "Couldn't recover PCM device after 10 tries, aborting\n");

	      update_status(LAUDIO_FAILED);
	      return;
	    }
	}

      nsamp = snd_pcm_writei(hdl, pkt->samples + pkt->offset, BTOS(sizeof(pkt->samples) - pkt->offset));
      if ((nsamp == -EPIPE) || (nsamp == -ESTRPIPE))
	{
	  ret = laudio_alsa_xrun_recover(nsamp);
	  if ((ret < 0) || (ret == 1))
	    {
	      if (ret < 0)
		DPRINTF(E_LOG, L_LAUDIO, "PCM write error: %s\n", snd_strerror(ret));

	      update_status(LAUDIO_FAILED);
	      return;
	    }
	  else if (ret != 0)
	    return;

	  continue;
	}
      else if (nsamp < 0)
	{
	  DPRINTF(E_LOG, L_LAUDIO, "PCM write error: %s\n", snd_strerror(nsamp));

	  update_status(LAUDIO_FAILED);
	  return;
	}

      pcm_pos += nsamp;

      pkt->offset += STOB(nsamp);
      if (pkt->offset == sizeof(pkt->samples))
	{
	  pcm_pkt_head = pkt->next;

	  if (pkt == pcm_pkt_tail)
	    pcm_pkt_tail = NULL;

	  free(pkt);

	  pkt = pcm_pkt_head;
	}

      /* Don't let ALSA fill up the buffer too much */
// Disabled - seems to cause buffer underruns
//      if (nsamp == AIRTUNES_V2_PACKET_SAMPLES)
//	return;
    }
}
ssize_t AudioStreamOutALSA::write(const void *buffer, size_t bytes)
{
    android::AutoMutex lock(mLock);

    if (!mPowerLock) {
        acquire_wake_lock (PARTIAL_WAKE_LOCK, "AudioOutLock");
        mPowerLock = true;
    }

    acoustic_device_t *aDev = acoustics();

    // For output, we will pass the data on to the acoustics module, but the actual
    // data is expected to be sent to the audio device directly as well.
    if (aDev && aDev->write)
        aDev->write(aDev, buffer, bytes);

    snd_pcm_sframes_t n;
    size_t            sent = 0;
    status_t          err = 0;

    do {
        if (mHandle->mmap)
            n = snd_pcm_mmap_writei(mHandle->handle,
                               (char *)buffer + sent,
                               snd_pcm_bytes_to_frames(mHandle->handle, bytes - sent));
	else
            n = snd_pcm_writei(mHandle->handle,
                               (char *)buffer + sent,
                               snd_pcm_bytes_to_frames(mHandle->handle, bytes - sent));
        if (n == -EBADFD) {
            LOGW("badstate and do recovery.....");
            switch(snd_pcm_state(mHandle->handle)){
                case SND_PCM_STATE_SETUP:
                    err = snd_pcm_prepare(mHandle->handle);
                    if(err < 0) LOGW("snd_pcm_prepare failed");
                    break;
                case SND_PCM_STATE_SUSPENDED:
                    snd_pcm_resume(mHandle->handle);
                    if(err < 0) LOGW("snd_pcm_resume failed");
                    snd_pcm_prepare(mHandle->handle);
                    if(err < 0) LOGW("snd_pcm_prepare failed");
                    break;
                default:
                    // Somehow the stream is in a bad state. The driver probably
                    // has a bug and snd_pcm_recover() doesn't seem to handle this.
                    mHandle->module->open(mHandle, mHandle->curDev, mHandle->curMode);
                    break;
            }

            if(err < 0 ) mHandle->module->open(mHandle, mHandle->curDev, mHandle->curMode);

            if (aDev && aDev->recover) aDev->recover(aDev, n);
        }
        else if (n < 0) {
            if (mHandle->handle) {
                LOGW("underrun and do recovery.....");
                // snd_pcm_recover() will return 0 if successful in recovering from
                // an error, or -errno if the error was unrecoverable.
                n = snd_pcm_recover(mHandle->handle, n, 1);

                if (aDev && aDev->recover) aDev->recover(aDev, n);

                if (n) return static_cast<ssize_t>(n);
            }
        }
        else {
            mFrameCount += n;
            sent += static_cast<ssize_t>(snd_pcm_frames_to_bytes(mHandle->handle, n));
        }

    } while (mHandle->handle && sent < bytes);

    return sent;
}