Exemplo n.º 1
0
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
{
	int err;

	/* get the current swparams */
	err = alsa_pcm_sw_params_current(handle, swparams);
	if (err < 0) {
		printf("Unable to determine current swparams for playback: %s\n", alsa_strerror(err));
		return err;
	}
	/* start the transfer when the buffer is almost full: */
	/* (buffer_size / avail_min) * avail_min */
	err = alsa_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size_in_frames / period_size) * period_size);
	if (err < 0) {
		printf("Unable to set start threshold mode for playback: %s\n", alsa_strerror(err));
		return err;
	}
	/* allow the transfer when at least period_size samples can be processed */
	/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
	err = alsa_pcm_sw_params_set_avail_min(handle, swparams, period_size);
	if (err < 0) {
		printf("Unable to set avail min for playback: %s\n", alsa_strerror(err));
		return err;
	}
	/* write the parameters to the playback device */
	err = alsa_pcm_sw_params(handle, swparams);
	if (err < 0) {
		printf("Unable to set sw params for playback: %s\n", alsa_strerror(err));
		return err;
	}
	return 0;
}
Exemplo n.º 2
0
static void ALSA_Update(void)
{
	int err;

	if (!enabled) return;

	if (bytes_written == 0 || bytes_played == bytes_written) {
		bytes_written = VC_WriteBytes(audiobuffer,period_size * global_frame_size);
		bytes_played = 0;
	}

	while (bytes_played < bytes_written)
	{
		err = alsa_pcm_writei(pcm_h, &audiobuffer[bytes_played], (bytes_written - bytes_played) / global_frame_size);
		if (err == -EAGAIN)
			continue;
		if (err < 0) {
			if ((err = xrun_recovery(pcm_h, err)) < 0) {
				_mm_errno = MMERR_ALSA_PCM_RECOVER;
				enabled = 0;
				dbgprint(stderr, "Write error: %s\n", alsa_strerror(err));
			}
			break;
		}
		bytes_played += err * global_frame_size;
	}
}
Exemplo n.º 3
0
static void ALSA_Update(void)
{
    int err;

    {
        if (bytes_written == 0 || bytes_played == bytes_written)
        {
            bytes_written = VC_WriteBytes(audiobuffer,buffer_size_in_frames * global_frame_size);
            bytes_played = 0;
        }

        while (bytes_played < bytes_written)
        {
            err = alsa_pcm_writei(pcm_h, &audiobuffer[bytes_played], (bytes_written - bytes_played) / global_frame_size);
            if (err == -EAGAIN)
            {
                continue;
            }
            if (err < 0) {
                if ((err = xrun_recovery(pcm_h, err)) < 0) {
                    printf("Write error: %s\n", alsa_strerror(err));
                    exit(-1);
                }
                break;
            }
            bytes_played += err * global_frame_size;
        }
    }
}
Exemplo n.º 4
0
static BOOL ALSA_Init_internal(void)
{
	snd_pcm_format_t pformat;
#ifdef OLD_ALSA
#define channels pformat.channels
#define rate pformat.rate
	int mask,card;
#else
    int rate;
    int channels;
    int err;
    snd_pcm_hw_params_t * hwparams;
	snd_pcm_sw_params_t * swparams;
#endif

	/* adjust user-configurable settings */
	if((getenv("MM_NUMFRAGS"))&&(numfrags==DEFAULT_NUMFRAGS)) {
		numfrags=atoi(getenv("MM_NUMFRAGS"));
		if ((numfrags<2)||(numfrags>16)) numfrags=DEFAULT_NUMFRAGS;
	}
#ifdef OLD_ALSA
	if((getenv("ALSA_CARD"))&&(!cardmin)&&(cardmax==SND_CARDS)) {
		cardmin=atoi(getenv("ALSA_CARD"));
		cardmax=cardmin+1;
#endif
		if(getenv("ALSA_PCM"))
			device=atoi(getenv("ALSA_PCM"));
#ifdef OLD_ALSA
	}
#endif

	/* setup playback format structure */
#define NUM_CHANNELS() ((md_mode&DMODE_STEREO)?2:1)

#ifdef OLD_ALSA
	memset(&pformat,0,sizeof(pformat));
#ifdef SND_LITTLE_ENDIAN
	pformat.format=(md_mode&DMODE_16BITS)?SND_PCM_SFMT_S16_LE:SND_PCM_SFMT_U8;
#else
	pformat.format=(md_mode&DMODE_16BITS)?SND_PCM_SFMT_S16_BE:SND_PCM_SFMT_U8;
#endif
#else
    pformat = (md_mode&DMODE_16BITS)?SND_PCM_FORMAT_S16_LE:SND_PCM_FORMAT_U8;
    snd_pcm_hw_params_alloca(&hwparams);
	snd_pcm_sw_params_alloca(&swparams);
#endif
	channels = NUM_CHANNELS();
	rate=md_mixfreq;

	/* scan for appropriate sound card */
#ifdef OLD_ALSA
	mask=alsa_cards_mask();
#endif
	_mm_errno=MMERR_OPENING_AUDIO;
#ifdef OLD_ALSA
	for (card=cardmin;card<cardmax;card++)
#endif
    {
#ifdef OLD_ALSA
		struct snd_ctl_hw_info info;
		snd_ctl_t *ctl_h;
		int dev,devmin,devmax;
#endif

#ifdef OLD_ALSA
		/* no card here, onto the next */
		if (!(mask&(1<<card))) continue;
#endif

#ifdef OLD_ALSA
		/* try to open the card in query mode */
		if (alsa_ctl_open(&ctl_h,card)<0)
			continue;
#else
        if ((err = alsa_pcm_open(&pcm_h, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
        {
            printf("snd_pcm_open() call failed: %s\n", alsa_strerror(err));
            goto END;
        }
#endif

#ifdef OLD_ALSA
		/* get hardware information */
		if(alsa_ctl_hw_info(ctl_h,&info)<0) {
			alsa_ctl_close(ctl_h);
			continue;
		}

		/* scan subdevices */
		if(device==-1) {
			devmin=0;devmax=info.pcmdevs;
		} else
			devmin=devmax=device;
#endif

#ifdef OLD_ALSA
		for(dev=devmin;dev<devmax;dev++)
#endif
        {
#ifdef OLD_ALSA
			int size,bps;
			snd_pcm_info_t pcminfo;
			snd_pcm_playback_info_t ctlinfo;
			struct snd_pcm_playback_info pinfo;
			struct snd_pcm_playback_params pparams;

			/* get PCM capabilities */
			if(alsa_ctl_pcm_info(ctl_h,dev,&pcminfo)<0)
				continue;

			/* look for playback capability */
			if(!(pcminfo.flags&SND_PCM_INFO_PLAYBACK))
				continue;

			/* get playback information */
#if defined(SND_LIB_VERSION) && (SND_LIB_VERSION >= 0x400)
			if(alsa_ctl_pcm_playback_info(ctl_h,dev,0,&ctlinfo)<0)
				continue;
#else
			if(alsa_ctl_pcm_playback_info(ctl_h,dev,&ctlinfo)<0)
				continue;
#endif

	/*
	   If control goes here, we have found a sound device able to play PCM data.
	   Let's open in in playback mode and see if we have compatible playback
	   settings.
	*/

			if (alsa_pcm_open(&pcm_h,card,dev,SND_PCM_OPEN_PLAYBACK)<0)
				continue;

			if (alsa_pcm_playback_info(pcm_h,&pinfo)<0) {
				alsa_pcm_close(pcm_h);
				pcm_h=NULL;
				continue;
			}

			/* check we have compatible settings */
			if((pinfo.min_rate>rate)||(pinfo.max_rate<rate)||
			   (!(pinfo.formats&(1<<pformat.format)))) {
				alsa_pcm_close(pcm_h);
				pcm_h=NULL;
				continue;
			}

			fragmentsize=pinfo.buffer_size/numfrags;
#ifdef MIKMOD_DEBUG
			if ((fragmentsize<512)||(fragmentsize>16777216L))
				fprintf(stderr,"\rweird pinfo.buffer_size:%d\n",pinfo.buffer_size);
#endif

			alsa_pcm_flush_playback(pcm_h);

			/* set new parameters */
			if(alsa_pcm_playback_format(pcm_h,&pformat)<0)
#else
            if( alsa_pcm_set_params(pcm_h, pformat, 
                SND_PCM_ACCESS_RW_INTERLEAVED,
                channels,
                rate,
                1,
                500000 /* 0.5sec */
                ) < 0)
#endif
            {
				alsa_pcm_close(pcm_h);
				pcm_h=NULL;
#ifdef OLD_ALSA
				continue;
#else
                goto END;
#endif
			}

            global_frame_size = channels*(md_mode&DMODE_16BITS?2:1);
#ifdef OLD_ALSA
			/* compute a fragmentsize hint
			   each fragment should be shorter than, but close to, half a
			   second of playback */
			bps=(rate*global_frame_size)>>1;
			size=fragmentsize;while (size>bps) size>>=1;
#endif
#ifdef MIKMOD_DEBUG
			if (size < 16) {
				fprintf(stderr,"\rweird hint result:%d from %d, bps=%d\n",size,fragmentsize,bps);
				size=16;
			}
#endif
#ifdef OLD_ALSA
         buffer_size = size;
			memset(&pparams,0,sizeof(pparams));
			pparams.fragment_size=size;
			pparams.fragments_max=-1; /* choose the best */
			pparams.fragments_room=-1;
			if(alsa_pcm_playback_params(pcm_h,&pparams)<0)
            {
				alsa_pcm_close(pcm_h);
				pcm_h=NULL;
				continue;
			}
#else
            /* choose all parameters */
            err = alsa_pcm_hw_params_any(pcm_h, hwparams);
            if (err < 0) {
                printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
                goto END;
            }

            {
                snd_pcm_uframes_t temp_u_buffer_size, temp_u_period_size;
                err = alsa_pcm_get_params(pcm_h, &temp_u_buffer_size, &temp_u_period_size);
                if (err < 0) {
                    alsa_pcm_close(pcm_h);
                    pcm_h=NULL;
                    printf("Unable to get buffer size for playback: %s\n", alsa_strerror(err));
                    goto END;
                }
                buffer_size_in_frames = 1200;
                period_size = temp_u_period_size;
            }

            /* The set_swparams function was taken from test/pcm.c
             * in the alsa-lib distribution*/
            if ((err = set_swparams(pcm_h, swparams)) < 0) {
                printf("Setting of swparams failed: %s\n", snd_strerror(err));
                goto END;
            }
#endif

			if (!(audiobuffer=(SBYTE*)MikMod_malloc(
#ifdef OLD_ALSA
                        fragmentsize
#else
                        buffer_size_in_frames * global_frame_size
#endif
                        ))) {
#ifdef OLD_ALSA
				alsa_ctl_close(ctl_h);
#else
                alsa_pcm_close(pcm_h);
#endif
				return 1;
			}

			/* sound device is ready to work */
			if (VC_Init()) {
#ifdef OLD_ALSA
				alsa_ctl_close(ctl_h);
#else
                alsa_pcm_close(pcm_h);
#endif
				return 1;
			} else
			  return 0;
		}

#ifdef OLD_ALSA
		alsa_ctl_close(ctl_h);
#else
        alsa_pcm_close(pcm_h);
#endif
	}
END:
	return 1;
}