Example #1
0
static BOOL ALSA_Init_internal(void)
{
	snd_pcm_format_t pformat;
	int mask,card;

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

	/* setup playback format structure */
	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
	pformat.channels=(md_mode&DMODE_STEREO)?2:1;
	pformat.rate=md_mixfreq;

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

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

		/* try to open the card in query mode */
		if(alsa_ctl_open(&ctl_h,card)<0)
			continue;

		/* 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;
		for(dev=devmin;dev<devmax;dev++) {
			snd_pcm_info_t pcminfo;
			snd_pcm_playback_info_t ctlinfo;
			struct snd_pcm_playback_info pinfo;
			struct snd_pcm_playback_params pparams;
			int size,bps;

			/* 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>pformat.rate)||(pinfo.max_rate<pformat.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) {
				alsa_pcm_close(pcm_h);
				pcm_h=NULL;
				continue;
			}

			/* compute a fragmentsize hint
			   each fragment should be shorter than, but close to, half a
			   second of playback */
			bps=(pformat.rate*pformat.channels*(md_mode&DMODE_16BITS?2:1))>>1;
			size=fragmentsize;while (size>bps) size>>=1;
#ifdef MIKMOD_DEBUG
			if (size < 16) {
				fprintf(stderr,"\rweird hint result:%d from %d, bps=%d\n",size,fragmentsize,bps);
				size=16;
			}
#endif

			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;
			}

			if (!(audiobuffer=(SBYTE*)MikMod_malloc(fragmentsize))) {
				alsa_ctl_close(ctl_h);
				return 1;
			}

			/* sound device is ready to work */
			if (VC_Init()) {
				alsa_ctl_close(ctl_h);
				return 1;
			} else
			  return 0;
		}

		alsa_ctl_close(ctl_h);
	}
	return 0;
}
Example #2
0
int bx_sound_linux_c::startwaverecord(int frequency, int bits, bx_bool stereo, int format)
{
  Bit64u timer_val;
  Bit8u shift = 0;
  int fmt, ret;
  int signeddata = format & 1;

  if (record_timer_index != BX_NULL_TIMER_HANDLE) {
    if (bits == 16) shift++;
    if (stereo) shift++;
    record_packet_size = (frequency / 10) << shift; // 0.1 sec
    if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) {
      record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE;
    }
    timer_val = (Bit64u)record_packet_size * 1000000 / (frequency << shift);
    bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1);
  }
#if BX_HAVE_ALSASOUND
  if (use_alsa_pcm) {
    return alsa_pcm_open(1, frequency, bits, stereo, format);
  }
#endif
  if ((wave_device[1] == NULL) || (strlen(wave_device[1]) < 1))
    return BX_SOUNDLOW_ERR;

  if (wave_fd[1] == -1) {
    wave_fd[1] = open(wave_device[1], O_RDONLY);
    if (wave_fd[1] == -1) {
      return BX_SOUNDLOW_ERR;
    } else {
      BX_INFO(("OSS: opened input device %s", wave_device[1]));
    }
  } else {
    if ((frequency == wave_ch[0].oldfreq) &&
        (bits == wave_ch[0].oldbits) &&
        (stereo == wave_ch[0].oldstereo) &&
        (format == wave_ch[0].oldformat))
      return BX_SOUNDLOW_OK; // nothing to do
  }
  wave_ch[0].oldfreq = frequency;
  wave_ch[0].oldbits = bits;
  wave_ch[0].oldstereo = stereo;
  wave_ch[0].oldformat = format;

  if (bits == 16)
    if (signeddata == 1)
      fmt = AFMT_S16_LE;
    else
      fmt = AFMT_U16_LE;
  else if (bits == 8)
    if (signeddata == 1)
      fmt = AFMT_S8;
    else
      fmt = AFMT_U8;
  else
    return BX_SOUNDLOW_ERR;

      // set frequency etc.
  ret = ioctl(wave_fd[1], SNDCTL_DSP_RESET);
  if (ret != 0)
    BX_DEBUG(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)));

  ret = ioctl(wave_fd[1], SNDCTL_DSP_SETFMT, &fmt);
  if (ret != 0) {  // abort if the format is unknown, to avoid playing noise
    BX_DEBUG(("ioctl(SNDCTL_DSP_SETFMT, %d): %s",
              fmt, strerror(errno)));
    return BX_SOUNDLOW_ERR;
  }

  ret = ioctl(wave_fd[1], SNDCTL_DSP_STEREO, &stereo);
  if (ret != 0) {
    BX_DEBUG(("ioctl(SNDCTL_DSP_STEREO, %d): %s",
             stereo, strerror(errno)));
    return BX_SOUNDLOW_ERR;
  }

  ret = ioctl(wave_fd[1], SNDCTL_DSP_SPEED, &frequency);
  if (ret != 0) {
    BX_DEBUG(("ioctl(SNDCTL_DSP_SPEED, %d): %s",
             frequency, strerror(errno)));
    return BX_SOUNDLOW_ERR;
  }

  return BX_SOUNDLOW_OK;
}
Example #3
0
static int ALSA_Init_internal(void)
{
	snd_pcm_format_t pformat;
	unsigned int btime = 250000;	/* 250ms */
	unsigned int ptime = 50000;	/* 50ms */
	snd_pcm_uframes_t psize;
	snd_pcm_uframes_t bsize;
	unsigned int rate, channels;
	snd_pcm_hw_params_t * hwparams;
	int err;

	/* setup playback format structure */
	pformat = (md_mode&DMODE_FLOAT)? SND_PCM_FORMAT_FLOAT :
			(md_mode&DMODE_16BITS)? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8;
	channels = (md_mode&DMODE_STEREO)?2:1;
	rate = md_mixfreq;

#define MIKMOD_ALSA_DEVICE "default"
	if ((err = alsa_pcm_open(&pcm_h, MIKMOD_ALSA_DEVICE, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
		_mm_errno = MMERR_OPENING_AUDIO;
		goto END;
	}

	snd_pcm_hw_params_alloca(&hwparams);
	err = alsa_pcm_hw_params_any(pcm_h, hwparams);
	if (err < 0) {
		_mm_errno = MMERR_ALSA_NOCONFIG;
		goto END;
	}

	err = alsa_pcm_hw_params_set_access(pcm_h, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
	if (!err) err = alsa_pcm_hw_params_set_format(pcm_h, hwparams, pformat);
	if (!err) err = alsa_pcm_hw_params_set_rate_near(pcm_h, hwparams, &rate, NULL);
	if (!err) err = alsa_pcm_hw_params_set_channels_near(pcm_h, hwparams, &channels);
	if (!err) err = alsa_pcm_hw_params_set_buffer_time_near(pcm_h, hwparams, &btime, NULL);
	if (!err) err = alsa_pcm_hw_params_set_period_time_near(pcm_h, hwparams, &ptime, NULL);
	if (!err) err = alsa_pcm_hw_params(pcm_h, hwparams);
	if (err < 0) {
		_mm_errno = MMERR_ALSA_SETPARAMS;
		goto END;
	}

	if (rate != md_mixfreq) {
		_mm_errno = MMERR_ALSA_SETRATE;
		goto END;
	}
	if (!(md_mode&DMODE_STEREO) && channels != 1) {
		_mm_errno = MMERR_ALSA_SETCHANNELS;
		goto END;
	}
	if ((md_mode&DMODE_STEREO) && channels != 2) {
		_mm_errno = MMERR_ALSA_SETCHANNELS;
		goto END;
	}

	err = alsa_pcm_hw_params_current(pcm_h, hwparams);
	if (!err) err = alsa_pcm_hw_params_get_buffer_size(hwparams, &bsize);
	if (!err) err = alsa_pcm_hw_params_get_period_size(hwparams, &psize, NULL);
	if (err < 0) {
		_mm_errno = MMERR_ALSA_BUFFERSIZE;
		goto END;
	}

	period_size = psize;
	global_frame_size = channels *
				((md_mode&DMODE_FLOAT)? 4 : (md_mode&DMODE_16BITS)? 2 : 1);

	if (!(audiobuffer=(SBYTE*)MikMod_malloc(period_size * global_frame_size))) {
		_mm_errno = MMERR_OUT_OF_MEMORY;
		goto END;
	}

	/* sound device is ready to work */
	if (!VC_Init()) {
		enabled = 1;
		return 0;
	}
END:
	alsa_pcm_close(pcm_h);
	pcm_h = NULL;
	return 1;
}
Example #4
0
int bx_sound_linux_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format)
{
  int fmt, ret;
  int signeddata = format & 1;

#if BX_HAVE_ALSASOUND
  if (use_alsa_pcm) {
    return alsa_pcm_open(0, frequency, bits, stereo, format);
  }
#endif
  if ((wave_device[0] == NULL) || (strlen(wave_device[0]) < 1))
    return BX_SOUNDLOW_ERR;

  if (wave_fd[0] == -1) {
    wave_fd[0] = open(wave_device[0], O_WRONLY);
    if (wave_fd[0] == -1) {
      return BX_SOUNDLOW_ERR;
    } else {
      BX_INFO(("OSS: opened output device %s", wave_device[0]));
    }
  } else {
    if ((frequency == wave_ch[0].oldfreq) &&
        (bits == wave_ch[0].oldbits) &&
        (stereo == wave_ch[0].oldstereo) &&
        (format == wave_ch[0].oldformat))
      return BX_SOUNDLOW_OK; // nothing to do
  }
  wave_ch[0].oldfreq = frequency;
  wave_ch[0].oldbits = bits;
  wave_ch[0].oldstereo = stereo;
  wave_ch[0].oldformat = format;

  if (bits == 16)
    if (signeddata == 1)
      fmt = AFMT_S16_LE;
    else
      fmt = AFMT_U16_LE;
  else if (bits == 8)
    if (signeddata == 1)
      fmt = AFMT_S8;
    else
      fmt = AFMT_U8;
  else
    return BX_SOUNDLOW_ERR;

      // set frequency etc.
  ret = ioctl(wave_fd[0], SNDCTL_DSP_RESET);
  if (ret != 0)
    BX_DEBUG(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)));

  /*
  ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFRAGMENT, &fragment);
  if (ret != 0)
    BX_DEBUG(("ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s",
             fragment, strerror(errno)));
  */

  ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFMT, &fmt);
  if (ret != 0)   // abort if the format is unknown, to avoid playing noise
  {
      BX_DEBUG(("ioctl(SNDCTL_DSP_SETFMT, %d): %s",
               fmt, strerror(errno)));
      return BX_SOUNDLOW_ERR;
  }

  ret = ioctl(wave_fd[0], SNDCTL_DSP_STEREO, &stereo);
  if (ret != 0)
    BX_DEBUG(("ioctl(SNDCTL_DSP_STEREO, %d): %s",
             stereo, strerror(errno)));

  ret = ioctl(wave_fd[0], SNDCTL_DSP_SPEED, &frequency);
  if (ret != 0)
    BX_DEBUG(("ioctl(SNDCTL_DSP_SPEED, %d): %s",
             frequency, strerror(errno)));

  // ioctl(wave_fd[0], SNDCTL_DSP_GETBLKSIZE, &fragment);
  // BX_DEBUG(("current output block size is %d", fragment));

  return BX_SOUNDLOW_OK;
}
Example #5
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;
}