⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsa_a.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 3 页
字号:
  total_bytes = frag_size * frags;  ctl->cmsg(CMSG_INFO, VERB_VERBOSE,	    "Requested buffer size %d, fragment size %d",	    total_bytes, frag_size);  if ((tmp = snd_pcm_hw_params_set_buffer_size_near(handle, pinfo, total_bytes >> sample_shift)) < 0) {    ctl->cmsg(CMSG_WARNING, VERB_NORMAL,	      "ALSA pcm '%s' can't set buffer size %d",	      alsa_device_name(), total_bytes);    snd_pcm_close(handle);    return -1;  }  if ((tmp = snd_pcm_hw_params_set_period_size_near(handle, pinfo, frag_size >> sample_shift, 0)) < 0) {    ctl->cmsg(CMSG_WARNING, VERB_NORMAL,	      "ALSA pcm '%s' can't set period size %d",	      alsa_device_name(), frag_size);    snd_pcm_close(handle);    return -1;  }  if (snd_pcm_hw_params(handle, pinfo) < 0) {    snd_output_t *log;    ctl->cmsg(CMSG_WARNING, VERB_NORMAL,	      "ALSA pcm '%s' can't set hw_params", alsa_device_name());    snd_output_stdio_attach(&log, stderr, 0);    snd_pcm_hw_params_dump(pinfo, log);    snd_pcm_close(handle);    return -1;  }  total_bytes = snd_pcm_hw_params_get_buffer_size(pinfo) << sample_shift;  frag_size = snd_pcm_hw_params_get_period_size(pinfo, NULL) << sample_shift;  ctl->cmsg(CMSG_INFO, VERB_VERBOSE,	    "ALSA pcm '%s' set buffer size %d, period size %d bytes",	    alsa_device_name(), total_bytes, frag_size);  tmp = snd_pcm_hw_params_get_rate(pinfo, NULL);  if (tmp > 0 && tmp != dpm.rate) {    dpm.rate = tmp;    ret_val = 1;  }  if (orig_rate != dpm.rate) {    ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,	      "Output rate adjusted to %d Hz (requested %d Hz)",	      dpm.rate, orig_rate);  }  snd_pcm_sw_params_current(handle, swpinfo);  snd_pcm_sw_params_set_start_threshold(handle, swpinfo, total_bytes >> sample_shift);  snd_pcm_sw_params_set_stop_threshold(handle, swpinfo, total_bytes >> sample_shift);  tmp = snd_pcm_prepare(handle);  if (tmp < 0) {    ctl->cmsg(CMSG_WARNING, VERB_NORMAL,	      "unable to prepare channel\n");    snd_pcm_close(handle);    return -1;  }  pfds = snd_pcm_poll_descriptors_count(handle);  if (pfds > 1) {    ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "too many poll descriptors: %s",	      alsa_device_name());    close_output ();    return -1;  } else if (pfds == 1) {    struct pollfd pfd;    if (snd_pcm_poll_descriptors(handle, &pfd, 1) >= 0)      dpm.fd = pfd.fd;    else      dpm.fd = -1;  } else    dpm.fd = -1;  output_counter = 0;  return ret_val;}static void close_output(void){  if (handle) {    int ret = snd_pcm_close (handle);    if (ret < 0)      error_report (ret);    handle = NULL;  }  dpm.fd = -1;}static int output_data(char *buf, int32 nbytes){  int n;  int nframes, shift;  if (! handle)    return -1;  nframes = nbytes;  shift = 0;  if (!(dpm.encoding & PE_MONO))    shift++;  if (dpm.encoding & PE_16BIT)    shift++;  nframes >>= shift;    while (nframes > 0) {    n = snd_pcm_writei(handle, buf, nframes);    if (n == -EAGAIN || (n >= 0 && n < nframes)) {      snd_pcm_wait(handle, 1000);    } else if (n == -EPIPE) {      snd_pcm_status_t *status;      snd_pcm_status_alloca(&status);      if (snd_pcm_status(handle, status) < 0) {	ctl->cmsg(CMSG_WARNING, VERB_DEBUG, "%s: cannot get status", alsa_device_name());	return -1;      }      ctl->cmsg(CMSG_INFO, VERB_DEBUG,		"%s: underrun at %ld", alsa_device_name(), output_counter << sample_shift);      snd_pcm_prepare(handle);    } else if (n < 0) {      ctl->cmsg(CMSG_WARNING, VERB_DEBUG,		"%s: %s", alsa_device_name(),		(n < 0) ? snd_strerror(n) : "write error");      return -1;    }    if (n > 0) {      nframes -= n;      buf += n << shift;      output_counter += n;    }  }  return 0;}static int acntl(int request, void *arg){  snd_pcm_status_t *status;  snd_pcm_sframes_t delay;  if (handle == NULL)    return -1;  switch (request) {  case PM_REQ_GETFRAGSIZ:    if (frag_size == 0)      return -1;    *((int *)arg) = frag_size;    return 0;  case PM_REQ_GETQSIZ:    if (total_bytes == -1)      return -1;    *((int *)arg) = total_bytes;    return 0;  case PM_REQ_GETFILLABLE:    if (total_bytes == -1)      return -1;    snd_pcm_status_alloca(&status);    if (snd_pcm_status(handle, status) < 0)      return -1;    *((int *)arg) = snd_pcm_status_get_avail(status);    return 0;      case PM_REQ_GETFILLED:    if (total_bytes == -1)      return -1;    if (snd_pcm_delay(handle, &delay) < 0)      return -1;    *((int *)arg) = delay;    return 0;  case PM_REQ_GETSAMPLES:    if (total_bytes == -1)      return -1;    if (snd_pcm_delay(handle, &delay) < 0)      return -1;    *((int *)arg) = output_counter - delay;    return 0;  case PM_REQ_DISCARD:    if (snd_pcm_drop(handle) < 0)      return -1;    if (snd_pcm_prepare(handle) < 0)      return -1;    output_counter = 0;    return 0;  case PM_REQ_FLUSH:    if (snd_pcm_drain(handle) < 0)      return -1;    if (snd_pcm_prepare(handle) < 0)      return -1;    output_counter = 0;    return 0;  }  return -1;}/* end ALSA API 0.9.x */#elif ALSA_LIB == 5/*================================================================ * ALSA API version 0.5.x *================================================================*//*return value == 0 sucess               == 1 warning               == -1 fails */static int set_playback_info (snd_pcm_t* handle__,			      int32* encoding__, int32* rate__,			      const int32 extra_param[5]){  int ret_val = 0;  const int32 orig_rate = *rate__;  int tmp;  snd_pcm_channel_info_t   pinfo;  snd_pcm_channel_params_t pparams;  snd_pcm_channel_setup_t  psetup;  memset (&pinfo, 0, sizeof (pinfo));  memset (&pparams, 0, sizeof (pparams));  pinfo.channel = SND_PCM_CHANNEL_PLAYBACK;  tmp = snd_pcm_channel_info (handle__, &pinfo);  if (tmp < 0)    {      error_report (tmp);      return -1;    }  /*check sample bit*/  if (!(pinfo.formats & ~(SND_PCM_FMT_S8 | SND_PCM_FMT_U8)))    *encoding__ &= ~PE_16BIT; /*force 8bit samples*/  if (!(pinfo.formats & ~(SND_PCM_FMT_S16 | SND_PCM_FMT_U16)))    *encoding__ |= PE_16BIT; /*force 16bit samples*/  /*check rate*/  if (pinfo.min_rate > *rate__)    *rate__ = pinfo.min_rate;  if (pinfo.max_rate < *rate__)    *rate__ = pinfo.max_rate;  pparams.format.rate = *rate__;  /*check channels*/  if ((*encoding__ & PE_MONO) != 0 && pinfo.min_voices > 1)    *encoding__ &= ~PE_MONO;  if ((*encoding__ & PE_MONO) == 0 && pinfo.max_voices < 2)    *encoding__ |= PE_MONO;  if ((*encoding__ & PE_MONO) != 0)    pparams.format.voices = 1; /*mono*/  else    pparams.format.voices = 2; /*stereo*/  /*check format*/  if ((*encoding__ & PE_16BIT) != 0)    { /*16bit*/      if ((pinfo.formats & SND_PCM_FMT_S16_LE) != 0)	{	  pparams.format.format = SND_PCM_SFMT_S16_LE;	  *encoding__ |= PE_SIGNED;	}      else if ((pinfo.formats & SND_PCM_FMT_U16_LE) != 0)	{	  pparams.format.format = SND_PCM_SFMT_U16_LE;	  *encoding__ &= ~PE_SIGNED;	}      else if ((pinfo.formats & SND_PCM_FMT_S16_BE) != 0)	{	  pparams.format.format = SND_PCM_SFMT_S16_BE;	  *encoding__ |= PE_SIGNED;	}      else if ((pinfo.formats & SND_PCM_FMT_U16_BE) != 0)	{	  pparams.format.format = SND_PCM_SFMT_U16_BE;	  *encoding__ &= ~PE_SIGNED;	}      else	{	  ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		    "%s doesn't support 16 bit sample width",		    alsa_device_name());	  return -1;	}    }  else    { /*8bit*/      if ((pinfo.formats & SND_PCM_FMT_U8) != 0)	{	  pparams.format.format = SND_PCM_SFMT_U8;	  *encoding__ &= ~PE_SIGNED;	}#if 0      else if ((pinfo.formats & SND_PCM_FMT_S8) != 0)	{	  pcm_format.format = SND_PCM_SFMT_U16_LE;	  *encoding__ |= PE_SIGNED;	}#endif      else	{	  ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		    "%s doesn't support 8 bit sample width",		    alsa_device_name());	  return -1;	}    }  sample_shift = 0;  if (!(dpm.encoding & PE_MONO))    sample_shift++;  if (dpm.encoding & PE_16BIT)    sample_shift++;  /* Set buffer fragment size (in extra_param[1]) */  if (extra_param[1] != 0)    tmp = extra_param[1];  else    tmp = audio_buffer_size << sample_shift;  /* Set buffer fragments (in extra_param[0]) */  pparams.buf.block.frag_size = tmp;  pparams.buf.block.frags_max = (extra_param[0] == 0) ? -1 : extra_param[0];  pparams.buf.block.frags_min = 1;  pparams.mode = SND_PCM_MODE_BLOCK;  pparams.channel = SND_PCM_CHANNEL_PLAYBACK;  pparams.start_mode = SND_PCM_START_DATA; /* .. should be START_FULL */  pparams.stop_mode  = SND_PCM_STOP_STOP;  pparams.format.interleave = 1;  snd_pcm_channel_flush (handle__, SND_PCM_CHANNEL_PLAYBACK);  tmp = snd_pcm_channel_params (handle__, &pparams);  if (tmp < 0)    {      ctl->cmsg(CMSG_WARNING, VERB_NORMAL,		"%s doesn't support buffer fragments"		":request size=%d, max=%d, min=%d\n",		alsa_device_name(),		pparams.buf.block.frag_size,		pparams.buf.block.frags_max,		pparams.buf.block.frags_min);      return -1;    }  tmp = snd_pcm_channel_prepare (handle__, SND_PCM_CHANNEL_PLAYBACK);  if (tmp < 0)    {      ctl->cmsg(CMSG_WARNING, VERB_NORMAL,		"unable to prepare channel\n");      return -1;    }  memset (&psetup, 0, sizeof(psetup));  psetup.channel = SND_PCM_CHANNEL_PLAYBACK;  tmp = snd_pcm_channel_setup (handle__, &psetup);  if (tmp == 0)    {      if(psetup.format.rate != orig_rate)        {	  ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,		    "Output rate adjusted to %d Hz (requested %d Hz)",		    psetup.format.rate, orig_rate);	  dpm.rate = psetup.format.rate;	  ret_val = 1;	}      frag_size = psetup.buf.block.frag_size;      total_bytes = frag_size * psetup.buf.block.frags;    }  else    {      frag_size = 0;      total_bytes = -1; /* snd_pcm_playback_status fails */    }  return ret_val;}static int detect(void){  snd_pcm_t *pcm;  if (snd_pcm_open(&pcm, card, device, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK) < 0)    return 0;  snd_pcm_close(pcm);  return 1; /* found */}static int open_output(void){  int tmp, warnings=0;  int ret;  tmp = check_sound_cards (&card, &device, dpm.extra_param);  if (tmp < 0)    return -1;  /* Open the audio device */  ret = snd_pcm_open (&handle, card, device, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK);  if (ret < 0)    {      ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",		alsa_device_name(), snd_strerror (ret));      return -1;    }  snd_pcm_nonblock_mode(handle, 0); /* set back to blocking mode */  /* They can't mean these */  dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP);  warnings = set_playback_info (handle, &dpm.encoding, &dpm.rate,				dpm.extra_param);  if (warnings < 0)    {      close_output ();      return -1;    }  dpm.fd = snd_pcm_file_descriptor (handle, SND_PCM_CHANNEL_PLAYBACK);  output_counter = 0;  return warnings;}static void close_output(void){  int ret;  if (handle == NULL)    return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -