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; }
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; }
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(¶ms, 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, ¶ms)) < 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; }
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(¶ms, 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, ¶ms); 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; }
/* 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(¶ms, 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, ¶ms)) < 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; }
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; }
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(¶m, 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, ¶m); 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; }
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 (¶ms, 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, ¶ms)) < 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; }