コード例 #1
0
ファイル: audio_alsa.c プロジェクト: kichikuou/xsystem35-nacl
static int audio_open(audiodevice_t *dev, chanfmt_t fmt) {
	audio_alsa05_t *alsa = (audio_alsa05_t *)dev->data_pcm;
	
	snd_pcm_channel_params_t p;
	snd_pcm_channel_setup_t  s;
	
	if (0 > snd_pcm_open(&alsa->pcm_handle, alsa->card, alsa->pcm_dev, SND_PCM_OPEN_PLAYBACK)) {
		WARNING("Opening audio device %d failed\n", alsa->pcm_dev);
		goto _err_exit;
	}
	
	memset(&alsa->info, 0, sizeof(snd_pcm_channel_info_t));
	
	if (0 > snd_pcm_channel_info(alsa->pcm_handle, &alsa->info)) {
		WARNING("param get failed\n");
		goto _err_exit;
	}
	
	memset(&p, 0, sizeof(p));
	p.mode = SND_PCM_MODE_BLOCK;
	p.start_mode = SND_PCM_START_DATA;
	p.channel    = SND_PCM_CHANNEL_PLAYBACK;
	p.stop_mode  = SND_PCM_STOP_STOP;
	p.buf.block.frag_size = 1536;
	p.buf.block.frags_max =  6;
	p.buf.block.frags_min =  1;
	p.format.rate   = fmt.rate;
	p.format.format = fmt.bit == 8 ? SND_PCM_SFMT_U8 : SND_PCM_SFMT_S16;
	p.format.voices = fmt.ch;
	p.format.interleave = 1;
	alsa->silence  = fmt.bit == 8 ? 0x80 : 0;
	
	if (0 > snd_pcm_channel_params(alsa->pcm_handle, &p)) {
		WARNING("Unable to set channel params\n");
		goto _err_exit;
	}
	
	if (0 > snd_pcm_channel_prepare(alsa->pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) {
		WARNING("Unable to prepare channel\n");
		goto _err_exit;
	}
	
	memset(&s, 0, sizeof(s));
	s.mode    = SND_PCM_MODE_BLOCK;
	s.channel = SND_PCM_CHANNEL_PLAYBACK;
	
	if (0 > snd_pcm_channel_setup(alsa->pcm_handle, &s)) {
		WARNING("Unable to obtain setup\n");
		goto _err_exit;
	}
	
	dev->buf.len = s.buf.block.frag_size;
	dev->fd = snd_pcm_file_descriptor(alsa->pcm_handle, SND_PCM_CHANNEL_PLAYBACK); 
	return OK;
	
 _err_exit:
	dev->fd = -1;
	return NG;
}
コード例 #2
0
ファイル: pcm_qsa.c プロジェクト: BaJIeK/brltty
static int
reconfigurePcmChannel (PcmDevice *pcm, int errorLevel) {
    int code;
    if ((code = snd_pcm_channel_params(pcm->handle, &pcm->parameters)) >= 0) {
        snd_pcm_channel_setup_t setup;
        setup.channel = pcm->parameters.channel;
        if ((code = snd_pcm_channel_setup(pcm->handle, &setup)) >= 0) {
            pcm->parameters.mode = setup.mode;
            pcm->parameters.format = setup.format;
            pcm->parameters.buf.block.frag_size = setup.buf.block.frag_size;
            pcm->parameters.buf.block.frags_min = setup.buf.block.frags_min;
            pcm->parameters.buf.block.frags_max = setup.buf.block.frags_max;
            return 1;
        } else {
            logPcmError(errorLevel, "get channel setup", code);
        }
    } else {
        logPcmError(errorLevel, "set channel parameters", code);
    }
    return 0;
}
コード例 #3
0
ファイル: alsa_qsa.c プロジェクト: DSkywalk/RetroArch
static void *alsa_qsa_init(const char *device,
      unsigned rate, unsigned latency, unsigned block_frames,
      unsigned *new_rate)
{
   int err, card, dev, i;
   snd_pcm_channel_info_t pi;
   snd_pcm_channel_params_t params = {0};
   snd_pcm_channel_setup_t setup   = {0};
   alsa_t *alsa                    = (alsa_t*)calloc(1, sizeof(alsa_t));
   if (!alsa)
      return NULL;

   (void)device;
   (void)rate;
   (void)latency;

   if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev,
               SND_PCM_OPEN_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Audio open error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Can't set blocking mode: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&pi, 0, sizeof(pi));
   pi.channel = SND_PCM_CHANNEL_PLAYBACK;
   if ((err = snd_pcm_channel_info(alsa->pcm, &pi)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: snd_pcm_channel_info failed: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&params, 0, sizeof(params));

   params.channel = SND_PCM_CHANNEL_PLAYBACK;
   params.mode = SND_PCM_MODE_BLOCK;

   params.format.interleave = 1;
   params.format.format = SND_PCM_SFMT_S16_LE;
   params.format.rate = DEFAULT_RATE;
   params.format.voices = 2;

   params.start_mode = SND_PCM_START_FULL;
   params.stop_mode = SND_PCM_STOP_STOP;

   params.buf.block.frag_size = pi.max_fragment_size;
   params.buf.block.frags_min = 2;
   params.buf.block.frags_max = 8;

   RARCH_LOG("Fragment size: %d\n", params.buf.block.frag_size);
   RARCH_LOG("Min Fragment size: %d\n", params.buf.block.frags_min);
   RARCH_LOG("Max Fragment size: %d\n", params.buf.block.frags_max);

   if ((err = snd_pcm_channel_params(alsa->pcm, &params)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   setup.channel = SND_PCM_CHANNEL_PLAYBACK;

   if ((err = snd_pcm_channel_setup(alsa->pcm, &setup)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Read Back Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if (block_frames)
      alsa->buf_size = block_frames * 4;
   else
      alsa->buf_size = next_pow2(32 * latency);

   RARCH_LOG("[ALSA QSA]: buffer size: %u bytes\n", alsa->buf_size);

   alsa->buf_count = (latency * 4 * rate + 500) / 1000;
   alsa->buf_count = (alsa->buf_count + alsa->buf_size / 2) / alsa->buf_size;

   if ((err = snd_pcm_channel_prepare(alsa->pcm,
               SND_PCM_CHANNEL_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Prepare Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   alsa->buffer = (uint8_t**)calloc(sizeof(uint8_t*), alsa->buf_count);
   if (!alsa->buffer)
      goto error;

   alsa->buffer_chunk = (uint8_t*)calloc(alsa->buf_count, alsa->buf_size);
   if (!alsa->buffer_chunk)
      goto error;

   for (i = 0; i < alsa->buf_count; i++)
      alsa->buffer[i] = alsa->buffer_chunk + i * alsa->buf_size;

   alsa->has_float = false;
   alsa->can_pause = true;
   RARCH_LOG("[ALSA QSA]: Can pause: %s.\n",
         alsa->can_pause ? "yes" : "no");

   return alsa;

error:
   return (void*)-1;
}
コード例 #4
0
ファイル: alsapmo.cpp プロジェクト: mayhem/freeamp
Error AlsaPMO::Init(OutputInfo* info) 
{
    int                      err;
    snd_pcm_channel_params_t params;

    m_properlyInitialized = false;
    if (!info) 
    {
        info = myInfo;
    } 
    else 
    {
        // got info, so this is the beginning...
        m_iDataSize = info->max_buffer_size;

        err=snd_pcm_open(&m_handle, m_iCard, m_iDevice, 
                         SND_PCM_OPEN_PLAYBACK);
        if (err < 0)
        {
            ReportError("Audio device is busy. Please make sure that "
                        "another program is not using the device.");
            return (Error)pmoError_DeviceOpenFailed;
        }

        snd_pcm_nonblock_mode(m_handle, 1);
    }

    // configure the device:
    m_channels=info->number_of_channels;
    m_rate=info->samples_per_second;

    memset(&params, 0, sizeof(params)); 
    params.format.format = SND_PCM_SFMT_S16_LE;
    params.format.interleave = 1;
    params.format.voices = m_channels;
    params.format.rate = info->samples_per_second;
    params.channel = SND_PCM_CHANNEL_PLAYBACK;
    params.mode = SND_PCM_MODE_BLOCK;
    params.start_mode = SND_PCM_START_DATA;
    params.stop_mode = SND_PCM_STOP_STOP;
    params.buf.block.frag_size = m_iDataSize;
    params.buf.block.frags_max = 32;
    params.buf.block.frags_min = 1;

    err = snd_pcm_channel_params(m_handle, &params);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }
    err = snd_pcm_channel_prepare(m_handle, SND_PCM_CHANNEL_PLAYBACK);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }

    memcpy(myInfo, info, sizeof(OutputInfo));

    snd_pcm_channel_setup_t aInfo;
    aInfo.channel = SND_PCM_CHANNEL_PLAYBACK;
    err = snd_pcm_channel_setup(m_handle,&aInfo);
    if (err < 0)
    {
        ReportError("Cannot initialized audio device.");
        return (Error)pmoError_DeviceOpenFailed;
    }

    m_iOutputBufferSize = aInfo.buf.block.frag_size * aInfo.buf.block.frags;
    m_iBytesPerSample = info->number_of_channels * (info->bits_per_sample / 8);



    m_properlyInitialized = true;
    return kError_NoErr;
}
コード例 #5
0
ファイル: ao_alsa5.c プロジェクト: DanielGit/Intrisit8000
/*
    open & setup audio device
    return: 1=success 0=fail
*/
static int init(int rate_hz, int channels, int format, int flags)
{
    int err;
    int cards = -1;
    snd_pcm_channel_params_t params;
    snd_pcm_channel_setup_t setup;
    snd_pcm_info_t info;
    snd_pcm_channel_info_t chninfo;

    mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_InitInfo, rate_hz,
	channels, af_fmt2str_short(format));

    alsa_handler = NULL;

    mp_msg(MSGT_AO, MSGL_V, "alsa-init: compiled for ALSA-%s (%d)\n", SND_LIB_VERSION_STR,
        SND_LIB_VERSION);

    if ((cards = snd_cards()) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_SoundCardNotFound);
	return 0;
    }

    ao_data.format = format;
    ao_data.channels = channels;
    ao_data.samplerate = rate_hz;
    ao_data.bps = ao_data.samplerate*ao_data.channels;
    ao_data.outburst = OUTBURST;
    ao_data.buffersize = 16384;

    memset(&alsa_format, 0, sizeof(alsa_format));
    switch (format)
    {
	case AF_FORMAT_S8:
	    alsa_format.format = SND_PCM_SFMT_S8;
	    break;
	case AF_FORMAT_U8:
	    alsa_format.format = SND_PCM_SFMT_U8;
	    break;
	case AF_FORMAT_U16_LE:
	    alsa_format.format = SND_PCM_SFMT_U16_LE;
	    break;
	case AF_FORMAT_U16_BE:
	    alsa_format.format = SND_PCM_SFMT_U16_BE;
	    break;
	case AF_FORMAT_AC3_LE:
	case AF_FORMAT_S16_LE:
	    alsa_format.format = SND_PCM_SFMT_S16_LE;
	    break;
	case AF_FORMAT_AC3_BE:
	case AF_FORMAT_S16_BE:
	    alsa_format.format = SND_PCM_SFMT_S16_BE;
	    break;
	default:
	    alsa_format.format = SND_PCM_SFMT_MPEG;
	    break;
    }

    switch(alsa_format.format)
    {
	case SND_PCM_SFMT_S16_LE:
	case SND_PCM_SFMT_U16_LE:
	    ao_data.bps *= 2;
	    break;
	case -1:
	    mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_InvalidFormatReq,af_fmt2str_short(format));
	    return 0;
	default:
	    break;
    }

    switch(rate_hz)
    {
	case 8000:
	    alsa_rate = SND_PCM_RATE_8000;
	    break;
	case 11025:
	    alsa_rate = SND_PCM_RATE_11025;
	    break;
	case 16000:
	    alsa_rate = SND_PCM_RATE_16000;
	    break;
	case 22050:
	    alsa_rate = SND_PCM_RATE_22050;
	    break;
	case 32000:
	    alsa_rate = SND_PCM_RATE_32000;
	    break;
	case 44100:
	    alsa_rate = SND_PCM_RATE_44100;
	    break;
	case 48000:
	    alsa_rate = SND_PCM_RATE_48000;
	    break;
	case 88200:
	    alsa_rate = SND_PCM_RATE_88200;
	    break;
	case 96000:
	    alsa_rate = SND_PCM_RATE_96000;
	    break;
	case 176400:
	    alsa_rate = SND_PCM_RATE_176400;
	    break;
	case 192000:
	    alsa_rate = SND_PCM_RATE_192000;
	    break;
	default:
	    alsa_rate = SND_PCM_RATE_CONTINUOUS;
	    break;
    }

    alsa_format.rate = ao_data.samplerate;
    alsa_format.voices = ao_data.channels;
    alsa_format.interleave = 1;

    if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlayBackError, snd_strerror(err));
	return 0;
    }

    if ((err = snd_pcm_info(alsa_handler, &info)) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmInfoError, snd_strerror(err));
	return 0;
    }

    mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_SoundcardsFound,
	cards, info.name);

    if (info.flags & SND_PCM_INFO_PLAYBACK)
    {
	memset(&chninfo, 0, sizeof(chninfo));
	chninfo.channel = SND_PCM_CHANNEL_PLAYBACK;
	if ((err = snd_pcm_channel_info(alsa_handler, &chninfo)) < 0)
	{
	    mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmChanInfoError, snd_strerror(err));
	    return 0;
	}

#ifndef __QNX__
	if (chninfo.buffer_size)
	    ao_data.buffersize = chninfo.buffer_size;
#endif

	mp_msg(MSGT_AO, MSGL_V, "alsa-init: setting preferred buffer size from driver: %d bytes\n",
	    ao_data.buffersize);
    }

    memset(&params, 0, sizeof(params));
    params.channel = SND_PCM_CHANNEL_PLAYBACK;
    params.mode = SND_PCM_MODE_STREAM;
    params.format = alsa_format;
    params.start_mode = SND_PCM_START_DATA;
    params.stop_mode = SND_PCM_STOP_ROLLOVER;
    params.buf.stream.queue_size = ao_data.buffersize;
    params.buf.stream.fill = SND_PCM_FILL_NONE;

    if ((err = snd_pcm_channel_params(alsa_handler, &params)) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetParms, snd_strerror(err));
	return 0;
    }

    memset(&setup, 0, sizeof(setup));
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    setup.mode = SND_PCM_MODE_STREAM;
    setup.format = alsa_format;
    setup.buf.stream.queue_size = ao_data.buffersize;
    setup.msbits_per_sample = ao_data.bps;

    if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetChan, snd_strerror(err));
	return 0;
    }

    if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
	mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ChanPrepareError, snd_strerror(err));
	return 0;
    }

    mp_msg(MSGT_AO, MSGL_INFO, "AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n",
	ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize,
	snd_pcm_get_format_name(alsa_format.format));
    return 1;
}
コード例 #6
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    int mf, err;

    snd_pcm_format_t pf;

    //    snd_pcm_channel_info_t pcm_info;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;

    snd_pcm_channel_flush(d->soundfd, SND_PCM_CHANNEL_PLAYBACK);
    memset(&pp, 0, sizeof(pp));

    err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number, SND_PCM_OPEN_PLAYBACK);
    if (err != 0) {
	char buf[256];
	g_sprintf(buf, _("Couldn't open ALSA device for sound output (card:%d, device:%d):\n%s"), 
		d->card_number, d->device_number, snd_strerror(err));
	error_error(buf);
	goto out;
    }

    // ---
    // Set non-blocking mode.
    // ---
    //    snd_pcm_nonblock_mode(d->soundfd, 1);

    d->outtime = 0;
    d->bits = 0;
    mf = 0;

    // --
    // Set channel parameters
    // --
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;

    // ---
    // Select audio format
    // ---
    memset(&pf, 0, sizeof(pf));
    pf.interleave = 1;
    if (d->p_resolution == 16) {
      pf.format = SND_PCM_SFMT_S16_LE;
      d->bits = 16;
      mf = ST_MIXER_FORMAT_S16_LE;
    }
    else {
      pf.format = SND_PCM_SFMT_U8;
      d->bits = 8;
      mf = ST_MIXER_FORMAT_S8;
    }

    pf.rate = d->p_mixfreq;
    d->playrate = d->p_mixfreq;

    if(d->p_channels == 2) {
	d->stereo = 1;
	pf.voices = d->p_channels;
	mf |= ST_MIXER_FORMAT_STEREO;
    }
    else {
      pf.voices = d->p_channels;
      d->stereo = 0;
    }
    d->mf = mf;
    memcpy(&pp.format, &pf, sizeof(pf));

    //    pp.buf.block.frag_size = d->p_fragsize * pf.voices * (d->bits / 8);
    pp.buf.block.frag_size = d->p_fragsize;
    pp.buf.block.frags_max = -1;
    pp.buf.block.frags_min = 1;

    err = snd_pcm_channel_params(d->soundfd, &pp);
    if (err < 0) {
      error_error(_("Required output-channel parameters not supported.\n"));
      goto out;
    }

    if (snd_pcm_channel_prepare(d->soundfd, SND_PCM_CHANNEL_PLAYBACK) < 0) {
      error_error(_("Unable to prepare ALSA channel.\n"));
      goto out;
    }

    // ---
    // Get buffering parameters
    // ---
   
    memset(&setup, 0, sizeof(setup));
    setup.mode = SND_PCM_MODE_BLOCK;
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    err = snd_pcm_channel_setup(d->soundfd, &setup);
    if (err < 0) {
      error_error(_("Alsa setup error.\n"));
      goto out;
    }

    //    snd_pcm_channel_status(d->soundfd, &pbstat);
    //    d->fragsize = pbstat.fragment_size;

    d->numfrags = setup.buf.block.frags;
    d->fragsize = setup.buf.block.frag_size;
    /*    fprintf(stderr, "Numfrags: %d\n", d->numfrags);
	  fprintf(stderr, "Fragsize: %d\n", d->fragsize); */

    d->sndbuf = calloc(1, d->fragsize);

    if(d->stereo == 1) { 
      d->fragsize /= 2;  
    } 
    if(d->bits == 16) {  
      d->fragsize /= 2;  
    } 
    
    d->polltag = audio_poll_add(snd_pcm_file_descriptor(d->soundfd, SND_PCM_CHANNEL_PLAYBACK), GDK_INPUT_WRITE, alsa_poll_ready_playing, d);
    /*    d->firstpoll = TRUE; */
    d->firstpoll = TRUE;
    d->playtime = 0;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}
コード例 #7
0
int ao_plugin_open(ao_device *device, ao_sample_format *format)
{
	ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;

	snd_pcm_channel_params_t param;
	int err;

	memset(&param, 0, sizeof(param));

	param.channel = SND_PCM_CHANNEL_PLAYBACK;
	param.mode = SND_PCM_MODE_BLOCK;

	param.format.interleave = 1;

	switch (format->bits) {
	case 8  : param.format.format = SND_PCM_SFMT_S8;
		  break;
        case 16 : param.format.format = 
		    device->client_byte_format == AO_FMT_BIG ?
		    SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_S16_LE;
	          device->driver_byte_format = device->client_byte_format;
		  break;
	default : return 0;
	}

	if (format->channels == 1 || format->channels == 2)
		param.format.voices = format->channels;
	else
		return 0;

	/* Finish filling in the parameter structure */
	param.format.rate = format->rate;

	param.start_mode = SND_PCM_START_FULL;
	
	param.stop_mode = SND_PCM_STOP_STOP;

	param.buf.block.frag_size = internal->buf_size;
	param.buf.block.frags_min = 1;
	param.buf.block.frags_max = 8;

	internal->buf = malloc(internal->buf_size);
	internal->buf_end = 0;
	if (internal->buf == NULL)
	  return 0;  /* Could not alloc swap buffer */


	/* Open the ALSA device */
	err = snd_pcm_open(&(internal->pcm_handle), 
			   internal->card, 
			   internal->dev,
			   SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK);
	if (err < 0) {
		free(internal->buf);
		return 0;
	}

	err = snd_pcm_channel_params(internal->pcm_handle, &param);

	if (err < 0) {
		snd_pcm_close(internal->pcm_handle);
		free(internal->buf);
		return 0;
	}

	snd_pcm_nonblock_mode(internal->pcm_handle, 0);
	snd_pcm_channel_prepare(internal->pcm_handle, 
				SND_PCM_CHANNEL_PLAYBACK);

	return 1;
}
コード例 #8
0
ファイル: snd_alsa_0_5.c プロジェクト: luaman/qforge-newtree
qboolean
SNDDMA_Init (void)
{
	int         rc = 0, i;
	char       *err_msg = "";
	int         rate = -1, format = -1, bps, stereo = -1, frag_size;
	unsigned int mask;

	mask = snd_cards_mask ();
	if (!mask) {
		Con_Printf ("No sound cards detected\n");
		return 0;
	}
	if ((i = COM_CheckParm ("-sndcard")) != 0) {
		card = atoi (com_argv[i + 1]);
	}
	if ((i = COM_CheckParm ("-snddev")) != 0) {
		dev = atoi (com_argv[i + 1]);
	}
	if ((i = COM_CheckParm ("-sndbits")) != 0) {
		i = atoi (com_argv[i + 1]);
		if (i == 16) {
			format = SND_PCM_SFMT_S16_LE;
		} else if (i == 8) {
			format = SND_PCM_SFMT_U8;
		} else {
			Con_Printf ("Error: invalid sample bits: %d\n", i);
			return 0;
		}
	}
	if ((i = COM_CheckParm ("-sndspeed")) != 0) {
		rate = atoi (com_argv[i + 1]);
		if (rate != 44100 && rate != 22050 && rate != 11025) {
			Con_Printf ("Error: invalid sample rate: %d\n", rate);
			return 0;
		}
	}
	if ((i = COM_CheckParm ("-sndmono")) != 0) {
		stereo = 0;
	}
	if (card == -1) {
		for (card = 0; card < SND_CARDS; card++) {
			if (!(mask & (1 << card)))
				continue;
			rc = check_card (card);
			if (rc < 0)
				return 0;
			if (!rc)
				goto dev_openned;
		}
	} else {
		if (dev == -1) {
			rc = check_card (card);
			if (rc < 0)
				return 0;
			if (!rc)
				goto dev_openned;
		} else {
			if ((rc = snd_pcm_open (&pcm_handle, card, dev,
									SND_PCM_OPEN_PLAYBACK
									| SND_PCM_OPEN_NONBLOCK)) < 0) {
				Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
				return 0;
			}
			goto dev_openned;
		}
	}
	Con_Printf ("Error: audio open error: %s\n", snd_strerror (rc));
	return 0;

  dev_openned:
	Con_Printf ("Using card %d, device %d.\n", card, dev);
	memset (&cinfo, 0, sizeof (cinfo));
	cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
	snd_pcm_channel_info (pcm_handle, &cinfo);
	Con_Printf ("%08x %08x %08x\n", cinfo.flags, cinfo.formats, cinfo.rates);
	if ((rate == -1 || rate == 44100) && cinfo.rates & SND_PCM_RATE_44100) {
		rate = 44100;
		frag_size = 512;				/* assuming stereo 8 bit */
	} else if ((rate == -1 || rate == 22050)
			   && cinfo.rates & SND_PCM_RATE_22050) {
		rate = 22050;
		frag_size = 256;				/* assuming stereo 8 bit */
	} else if ((rate == -1 || rate == 11025)
			   && cinfo.rates & SND_PCM_RATE_11025) {
		rate = 11025;
		frag_size = 128;				/* assuming stereo 8 bit */
	} else {
		Con_Printf ("ALSA: desired rates not supported\n");
		goto error_2;
	}
	if ((format == -1 || format == SND_PCM_SFMT_S16_LE)
		&& cinfo.formats & SND_PCM_FMT_S16_LE) {
		format = SND_PCM_SFMT_S16_LE;
		bps = 16;
		frag_size *= 2;
	} else if ((format == -1 || format == SND_PCM_SFMT_U8)
			   && cinfo.formats & SND_PCM_FMT_U8) {
		format = SND_PCM_SFMT_U8;
		bps = 8;
	} else {
		Con_Printf ("ALSA: desired formats not supported\n");
		goto error_2;
	}
	if (stereo && cinfo.max_voices >= 2) {
		stereo = 1;
	} else {
		stereo = 0;
		frag_size /= 2;
	}

//  err_msg="audio flush";
//  if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
//      goto error;
	err_msg = "audio munmap";
	if ((rc = snd_pcm_munmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
		goto error;

	memset (&params, 0, sizeof (params));
	params.channel = SND_PCM_CHANNEL_PLAYBACK;
	params.mode = SND_PCM_MODE_BLOCK;
	params.format.interleave = 1;
	params.format.format = format;
	params.format.rate = rate;
	params.format.voices = stereo + 1;
	params.start_mode = SND_PCM_START_GO;
	params.stop_mode = SND_PCM_STOP_ROLLOVER;
	params.buf.block.frag_size = frag_size;
	params.buf.block.frags_min = 1;
	params.buf.block.frags_max = -1;
//  err_msg="audio flush";
//  if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0)
//      goto error;
	err_msg = "audio params";
	if ((rc = snd_pcm_channel_params (pcm_handle, &params)) < 0)
		goto error;

	err_msg = "audio mmap";
	if (
		(rc =
		 snd_pcm_mmap (pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control,
					   (void **) &mmap_data)) < 0)
		goto error;
	err_msg = "audio prepare";
	if ((rc = snd_pcm_plugin_prepare (pcm_handle, SND_PCM_CHANNEL_PLAYBACK)) <
		0) goto error;

	memset (&setup, 0, sizeof (setup));
	setup.mode = SND_PCM_MODE_BLOCK;
	setup.channel = SND_PCM_CHANNEL_PLAYBACK;
	err_msg = "audio setup";
	if ((rc = snd_pcm_channel_setup (pcm_handle, &setup)) < 0)
		goto error;

	shm = &sn;
	memset ((dma_t *) shm, 0, sizeof (*shm));
	shm->splitbuffer = 0;
	shm->channels = setup.format.voices;
	shm->submission_chunk = 128;		// don't mix less than this #
	shm->samplepos = 0;					// in mono samples
	shm->samplebits = setup.format.format == SND_PCM_SFMT_S16_LE ? 16 : 8;
	shm->samples =
		setup.buf.block.frags * setup.buf.block.frag_size / (shm->samplebits / 8);	// mono 
																					// samples 
																					// in 
																					// buffer
	shm->speed = setup.format.rate;
	shm->buffer = (unsigned char *) mmap_data;
	Con_Printf ("%5d stereo\n", shm->channels - 1);
	Con_Printf ("%5d samples\n", shm->samples);
	Con_Printf ("%5d samplepos\n", shm->samplepos);
	Con_Printf ("%5d samplebits\n", shm->samplebits);
	Con_Printf ("%5d submission_chunk\n", shm->submission_chunk);
	Con_Printf ("%5d speed\n", shm->speed);
	Con_Printf ("0x%x dma buffer\n", (int) shm->buffer);
	Con_Printf ("%5d total_channels\n", total_channels);

	snd_inited = 1;
	return 1;
  error:
	Con_Printf ("Error: %s: %s\n", err_msg, snd_strerror (rc));
  error_2:
	snd_pcm_close (pcm_handle);
	return 0;
}