示例#1
0
/*
 * open the audio device for writing to
 *
 * Implicit assumptions about audio format (bits/rate/mode):
 *
 * bits == 16: We always get 16-bit samples in native endian format,
 * 	using signed linear encoding
 *
 * bits ==  8: 8-bit samples use unsigned linear encoding,
 *	other 8-bit formats (uLaw, aLaw, etc) are currently not supported
 *	by xine
 */
static int ao_sun_open(ao_driver_t *this_gen,
		       uint32_t bits, uint32_t rate, int mode)
{
  sun_driver_t *this = (sun_driver_t *) this_gen;
  audio_info_t info;
  int pass;
  int ok;

  if (this->xine->verbosity >= XINE_VERBOSITY_LOG)
    printf ("audio_sun_out: ao_sun_open rate=%d, mode=%d\n", rate, mode);

  if ( (mode & this->capabilities) == 0 ) {
    if (this->xine->verbosity >= XINE_VERBOSITY_LOG)
      printf ("audio_sun_out: unsupported mode %08x\n", mode);
    return 0;
  }

  if (this->audio_fd >= 0) {

    if ( (mode == this->mode) && (rate == this->input_sample_rate) )
      return this->output_sample_rate;

    close (this->audio_fd);
  }
  
  this->mode			= mode;
  this->input_sample_rate	= rate;
  this->frames_in_buffer	= 0;

  /*
   * open audio device
   */

  this->audio_fd = open(this->audio_dev, O_WRONLY|O_NONBLOCK);
  if(this->audio_fd < 0) {
    fprintf(stderr, "audio_sun_out: Opening audio device %s failed: %s\n",
	    this->audio_dev, strerror(errno));
    return 0;
  }
  
  /* We wanted non blocking open but now put it back to normal */
  fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL) & ~O_NONBLOCK);

  /*
   * configure audio device
   */
  for (ok = pass = 0; pass <= 5; pass++) {

      AUDIO_INITINFO(&info);
      info.play.channels = (mode & AO_CAP_MODE_STEREO)
	  ? AUDIO_CHANNELS_STEREO
	  : AUDIO_CHANNELS_MONO;
      info.play.precision = bits;
      info.play.encoding = bits == 8
	  ? AUDIO_ENCODING_LINEAR8
	  : AUDIO_ENCODING_LINEAR;
      info.play.sample_rate = this->input_sample_rate;
      info.play.eof = 0;
      info.play.samples = 0;

      this->convert_u8_s8 = 0;

      if (pass & 1) {
	  /*
	   * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is 
	   * not supported, but 8-bit signed encoding is.
	   *
	   * Try S8, and if it works, use our own U8->S8 conversion before
	   * sending the samples to the sound driver.
	   */
	  if (info.play.encoding != AUDIO_ENCODING_LINEAR8)
	      continue;
	  info.play.encoding = AUDIO_ENCODING_LINEAR;
	  this->convert_u8_s8 = 1;
      }

      if (pass & 2) {
	  /*
	   * on some sun audio drivers, only certain fixed sample rates are
	   * supported.
	   *
	   * In case the requested sample rate is very close to one of the
	   * supported rates,  use the fixed supported rate instead.
	   *
	   * XXX: assuming the fixed supported rate works, should we
	   * lie with our return value and report the requested input
	   * sample rate, to avoid the software resample code?
	   */
	  if (!(info.play.sample_rate =
		find_close_samplerate_match(this->audio_fd,
					    this->input_sample_rate))) 
	      continue;
      }

      if (pass & 4) {
	  /* like "pass & 2", but use the highest supported sample rate */
	  if (!(info.play.sample_rate = find_highest_samplerate(this->audio_fd)))
	      continue;
      }

      if ((ok = ioctl(this->audio_fd, AUDIO_SETINFO, &info) >= 0)) {
	  /* audio format accepted by audio driver */
	  break;
      }

      /*
       * format not supported?
       * retry with different encoding and/or sample rate
       */
  }

  if (!ok) {
      fprintf(stderr, "audio_sun_out: Cannot configure audio device for "
	      "%dhz, %d channel, %d bits: %s\n",
	      rate, info.play.channels, bits, strerror(errno));
      close(this->audio_fd);
      this->audio_fd = -1;
      return 0;
  }

  this->last_samplecnt = 0;

  this->output_sample_rate = info.play.sample_rate;
  this->num_channels = info.play.channels;

  this->bytes_per_frame = 1;
  if (info.play.channels == AUDIO_CHANNELS_STEREO)
    this->bytes_per_frame *= 2;
  if (info.play.precision == 16)
    this->bytes_per_frame *= 2;

#if	CS4231_WORKAROUND
  this->buf_len = 0;
#endif

  /*
  printf ("audio_sun_out: audio rate : %d requested, %d provided by device/sec\n",
	   this->input_sample_rate, this->output_sample_rate);
  */

  if (this->xine->verbosity >= XINE_VERBOSITY_LOG)
    printf ("audio_sun_out: %d channels output\n",this->num_channels);
  return this->output_sample_rate;
}
示例#2
0
文件: ao_sun.c 项目: azuwis/mplayer
// open & setup audio device
// return: 1=success 0=fail
static int init(int rate,int channels,int format,int flags){

    audio_info_t info;
    int pass;
    int ok;
    int convert_u8_s8;

    setup_device_paths();

    if (enable_sample_timing == RTSC_UNKNOWN
	&& !getenv("AO_SUN_DISABLE_SAMPLE_TIMING")) {
	enable_sample_timing = realtime_samplecounter_available(audio_dev);
    }

    mp_msg(MSGT_AO,MSGL_STATUS,"ao2: %d Hz  %d chans  %s [0x%X]\n",
	   rate,channels,af_fmt2str_short(format),format);

    audio_fd=open(audio_dev, O_WRONLY);
    if(audio_fd<0){
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_CantOpenAudioDev, audio_dev, strerror(errno));
	return 0;
    }

    if (af2sunfmt(format) == AUDIO_ENCODING_NONE)
      format = AF_FORMAT_S16_NE;

    for (ok = pass = 0; pass <= 5; pass++) { /* pass 6&7 not useful */

	AUDIO_INITINFO(&info);
	info.play.encoding = af2sunfmt(ao_data.format = format);
	info.play.precision =
	    (format==AF_FORMAT_S16_NE
	     ? AUDIO_PRECISION_16
	     : AUDIO_PRECISION_8);
	info.play.channels = ao_data.channels = channels;
	info.play.sample_rate = ao_data.samplerate = rate;

	convert_u8_s8 = 0;

	if (pass & 1) {
	    /*
	     * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is
	     * not supported, but 8-bit signed encoding is.
	     *
	     * Try S8, and if it works, use our own U8->S8 conversion before
	     * sending the samples to the sound driver.
	     */
#ifdef AUDIO_ENCODING_LINEAR8
	    if (info.play.encoding != AUDIO_ENCODING_LINEAR8)
#endif
		continue;
	    info.play.encoding = AUDIO_ENCODING_LINEAR;
	    convert_u8_s8 = 1;
	}

	if (pass & 2) {
	    /*
	     * on some sun audio drivers, only certain fixed sample rates are
	     * supported.
	     *
	     * In case the requested sample rate is very close to one of the
	     * supported rates,  use the fixed supported rate instead.
	     */
	    if (!(info.play.sample_rate =
		  find_close_samplerate_match(audio_fd, rate)))
	      continue;

	    /*
	     * I'm not returning the correct sample rate in
	     * |ao_data.samplerate|, to avoid software resampling.
	     *
	     * ao_data.samplerate = info.play.sample_rate;
	     */
	}

	if (pass & 4) {
	    /* like "pass & 2", but use the highest supported sample rate */
	    if (!(info.play.sample_rate
		  = ao_data.samplerate
		  = find_highest_samplerate(audio_fd)))
		continue;
	}

	ok = ioctl(audio_fd, AUDIO_SETINFO, &info) >= 0;
	if (ok) {
	    /* audio format accepted by audio driver */
	    break;
	}

	/*
	 * format not supported?
	 * retry with different encoding and/or sample rate
	 */
    }

    if (!ok) {
	char buf[128];
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_SUN_UnsupSampleRate,
	       channels, af_fmt2str(format, buf, 128), rate);
	return 0;
    }

    if (convert_u8_s8)
      ao_data.format = AF_FORMAT_S8;

    bytes_per_sample = channels * info.play.precision / 8;
    ao_data.bps = byte_per_sec = bytes_per_sample * ao_data.samplerate;
    ao_data.outburst = byte_per_sec > 100000 ? 16384 : 8192;

    reset();

    return 1;
}