Exemplo n.º 1
0
/* write as many blocks as is currently possible */
static void
sndio_update(int threaded)
{
	struct pollfd pfd;
	nfds_t nfds;
	int i, nblocks, nbytes;

	/* make sure counters have been updated */
	nfds = sio_pollfd(hdl, &pfd, POLLOUT);
	poll(&pfd, nfds, 0);
	if (!(sio_revents(hdl, &pfd) & POLLOUT))
		return;

	nblocks = (sndio_play_appbufsz - (sndio_playpos - sndio_realpos)) /
	    sndio_play_round;

	/* we got POLLOUT, so we can write something.  if we don't
	 * write anything, we could underrun.
	 */
	if (nblocks < 1)
		nblocks = 1;

	for (i = 0; i < nblocks; i++) {
		sio_write(hdl, sndio_play_bufdata, sndio_play_bufsize);
		sndio_playpos += sndio_play_round;
		if (sio_eof(hdl)) {
			/* print error message? */
			return;
		}
		_mix_some_samples((uintptr_t) sndio_play_bufdata, 0, sndio_signed);
	}
}
Exemplo n.º 2
0
/* psp_audio_channel_thread:
 *  This PSP thread manages the audio playing.
 */
static int psp_audio_channel_thread()
{
   while (psp_audio_on) {
      void *bufptr = &sound_buffer[curr_buffer];
      /* Asks to the Allegro mixer to fill the buffer */
      _mix_some_samples((uintptr_t)bufptr, 0, IS_SIGNED);
      /* Send mixed buffer to sound card */
      sceAudioOutputPannedBlocking(hw_channel, PSP_AUDIO_VOLUME_MAX,
         PSP_AUDIO_VOLUME_MAX, bufptr);
      curr_buffer = !curr_buffer;
   }

   sceKernelExitThread(0);

   return 0;
}
Exemplo n.º 3
0
/* jack_process:
 *  The JACK processing functions.
 */
static int jack_process (jack_nframes_t nframes, void *arg)
{
   jack_nframes_t i;
   /* TODO: Should be uint16_t and uint8_t? Endianess? */
   unsigned short *buffer16 = jack_buffer;
   unsigned char *buffer8 = jack_buffer;

   _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);

   jack_default_audio_sample_t *out_left = (jack_default_audio_sample_t *)
      jack_port_get_buffer (output_left, nframes);

   if (jack_stereo) {
      jack_default_audio_sample_t *out_right = (jack_default_audio_sample_t *)
	 jack_port_get_buffer (output_right, nframes);

      if (jack_16bit) {
	 for (i = 0; i < nframes; i++) {
	    out_left[i] = ((sample_t) buffer16[i * 2] - AMP16) / AMP16;
	    out_right[i] = ((sample_t) buffer16[i * 2 + 1] - AMP16) / AMP16;
	 }
      }
      else {
	 for (i = 0; i < nframes; i++) {
	    out_left[i] = ((sample_t) buffer8[i * 2] - AMP8) / (sample_t) AMP8;
	    out_right[i] = ((sample_t) buffer8[i * 2 + 1] - AMP8) / (sample_t) AMP8;
	 }
      }
   }
   else
   {
      if (jack_16bit) {
	 for (i = 0; i < nframes; i++) {
	    out_left[i] = ((sample_t) buffer16[i] - AMP16) / AMP16;
	 }
      }
      else {
	 for (i = 0; i < nframes; i++) {
	    out_left[i] = ((sample_t) buffer8[i] - AMP8) / AMP8;
	 }
      }
   }

   return 0;
}
Exemplo n.º 4
0
/* alsa_mix
 *  Mix and send some samples to ALSA.
 */
static void alsa_mix(void)
{
   int ret, samples = alsa_bufsize;
   unsigned char *ptr = alsa_bufdata;

   while (samples > 0) {
      ret = snd_pcm_writei(pcm_handle, ptr, samples);
      if (ret == -EAGAIN)
	 continue;

      if (ret < 0) {
	 if (xrun_recovery(pcm_handle, ret) < 0)
	    fprintf(stderr, "Write error: %s\n", snd_strerror(ret));
	 poll_next = 0;
	 break;  /* skip one period */
      }
      if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_RUNNING)
	 poll_next = 1;
      samples -= ret;
      ptr += ret * alsa_sample_size;
   }

   _mix_some_samples((uintptr_t)alsa_bufdata, 0, alsa_signed);
}
Exemplo n.º 5
0
/* jack_init:
 *  JACK init routine.
 */
static int jack_init(int input, int voices)
{
   const char **ports;
   char tmp[128];

   if (!jack_detect(input))
      return -1;

   jack_bufsize = get_config_int("sound", "jack_buffer_size",
      jack_bufsize);

   if (jack_bufsize == -1)
      jack_bufsize = jack_get_buffer_size (jack_client);

   /* Those are already read in from the config file by Allegro. */
   jack_16bit = (_sound_bits == 16 ? 1 : 0);
   jack_stereo = (_sound_stereo ? 1 : 0);

   /* Let Allegro mix in its native unsigned format. */
   jack_signed = 0;

   jack_set_process_callback (jack_client, jack_process, NULL);

   output_left = jack_port_register (jack_client, jack_stereo ? "left" : "mono",
      JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

   if (jack_stereo)
      output_right = jack_port_register (jack_client, "right",
         JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);

   jack_rate = jack_get_sample_rate (jack_client);

   jack_buffer = _AL_MALLOC_ATOMIC(jack_bufsize * (1 + jack_16bit) * (1 + jack_stereo));
   if (!jack_buffer) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot allocate audio buffer"));
      jack_exit (input);
      return -1;
   }

   digi_jack.voices = voices;

   if (_mixer_init(jack_bufsize *  (1 + jack_stereo), jack_rate,
      jack_stereo, jack_16bit, &digi_jack.voices)) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot init software mixer"));
      jack_exit (input);
      return -1;
   }

   _mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);

   if (jack_activate (jack_client)) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
         "Cannot activate Jack client"));
      jack_exit (input);
      return 1;
   }

   /* Try to connect the ports. Failure to connect is not critical, since with
    * JACK, users may connect/disconnect ports anytime, without Allegro caring.
    */
   if ((ports = jack_get_ports (jack_client, NULL, NULL,
      JackPortIsPhysical|JackPortIsInput)) == NULL) {
      TRACE (PREFIX_I "Cannot find any physical playback ports");
   }

   if (ports) {
      if (ports[0]) {
	 if (jack_connect (jack_client, jack_port_name (output_left), ports[0]) == 0)
	    TRACE (PREFIX_I "Connected left playback port to %s", ports[0]);
      }
      if (jack_stereo && ports[1]) {
	 if (jack_connect (jack_client, jack_port_name (output_right), ports[1]) == 0)
	    TRACE (PREFIX_I "Connected right playback port to %s", ports[1]);
      }
      _AL_FREE (ports);
   }

   uszprintf(jack_desc, sizeof(jack_desc),
      get_config_text ("Jack, client '%s': %d bits, %s, %d bps, %s"),
      jack_client_name, jack_16bit ? 16 : 8,
      uconvert_ascii((jack_signed ? "signed" : "unsigned"), tmp),
      jack_rate, uconvert_ascii((jack_stereo ? "stereo" : "mono"), tmp));

   return 0;
}
Exemplo n.º 6
0
static int
sndio_init(int input, int voices)
{
	char tmp1[128], tmp2[128];

	if (input) {
		digi_driver->rec_cap_bits = 16;
		digi_driver->rec_cap_stereo = TRUE;
		return 0;
	}

	if (open_sndio_device(0) != 0)
		return -1;

	sndio_play_bufdata = _AL_MALLOC_ATOMIC(sndio_play_bufsize);
	if (sndio_play_bufdata == 0) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not allocate audio buffer"));
		sio_close(hdl);
		return -1;
	}

	sndio_realpos = sndio_playpos = 0;
	sio_onmove(hdl, movecb, NULL);

	sndio_volume = 127;
	sio_onvol(hdl, volcb, NULL);

	if (!sio_start(hdl)) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not start sndio"));
		sio_close(hdl);
		return -1;
	}

	digi_sndio.voices = voices;

	/* first arg is total number of samples */
	if (_mixer_init(sndio_play_round * (_sound_stereo ? 2 : 1),
	    _sound_freq, _sound_stereo, ((_sound_bits == 16) ? 1 : 0),
	    &digi_sndio.voices) != 0) {
		ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
		    get_config_text("Can not init software mixer"));
		sio_close(hdl);
		return -1;
	}

	_mix_some_samples((uintptr_t) sndio_play_bufdata, 0, sndio_signed);

	/* Add audio interrupt.  */
	_unix_bg_man->register_func(sndio_update);

	uszprintf(sndio_desc, sizeof(sndio_desc),
	    get_config_text("%s: %d bits, %s, %d Hz, %s"),
	    "sndio device",
	    _sound_bits,
	    uconvert_ascii((sndio_signed ? "signed" : "unsigned"), tmp1),
	    _sound_freq,
	    uconvert_ascii((par.pchan == 2 ? "stereo" : "mono"), tmp2));

	digi_driver->desc = sndio_desc;

	return 0;
}
Exemplo n.º 7
0
/* alsa_init:
 *  ALSA init routine.
 */
static int alsa_init(int input, int voices)
{
   int ret = 0;
   char tmp1[128], tmp2[128];
   int format = 0;
   unsigned int numfrags = 0;
   snd_pcm_uframes_t fragsize;

   if (input) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
      return -1;
   }

   ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0));

   alsa_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_device", tmp2),
				   alsa_device);

   alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1),
				   uconvert_ascii("alsa_mixer_device", tmp2),
				   alsa_mixer_device);

   fragsize = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_fragsize", tmp2), 0);

   numfrags = get_config_int(uconvert_ascii("sound", tmp1),
			     uconvert_ascii("alsa_numfrags", tmp2),
			     ALSA_DEFAULT_NUMFRAGS);

   ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
   if (ret < 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
      return -1;
   }

   snd_mixer_open(&alsa_mixer, 0);

   if (alsa_mixer
       && snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0
       && snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0
       && snd_mixer_load(alsa_mixer) >= 0) {
      const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1),
							   uconvert_ascii("alsa_mixer_elem", tmp2),
							   "PCM");

      alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer);

      while (alsa_mixer_elem) {
	 const char *name = snd_mixer_selem_get_name(alsa_mixer_elem);

	 if (strcasecmp(name, alsa_mixer_elem_name) == 0) {
	    snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max);
	    alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255;
	    break;
	 }

	 alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem);
      }
   }

   /* Set format variables. */
   alsa_bits = (_sound_bits == 8) ? 8 : 16;
   alsa_stereo = (_sound_stereo) ? 1 : 0;
   alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100;
   alsa_signed = 0;

   format = ((alsa_bits == 16) ? SND_PCM_FORMAT_U16_NE : SND_PCM_FORMAT_U8);

   switch (format) {

      case SND_PCM_FORMAT_U8:
	 alsa_bits = 8;
	 break;

      case SND_PCM_FORMAT_U16_NE:
	 if (sizeof(short) != 2) {
	    ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	    goto Error;
	 }
	 break;

      default:
	 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
	 goto Error;
   }

   alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1);

   if (fragsize == 0) {
      unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags;
      fragsize = 1;
      while (fragsize < size)
	 fragsize <<= 1;
   }

   snd_pcm_hw_params_malloc(&hwparams);
   snd_pcm_sw_params_malloc(&swparams);

   ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams));
   ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED));
   ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format));
   ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1));

   ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL)); 

   ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams));

   ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL));
   ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL));

   TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments);

   ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams));
   ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize));
   ALSA9_CHECK(snd_pcm_sw_params_set_xfer_align(pcm_handle, swparams, 1));
   ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams));

   /* Allocate mixing buffer. */
   alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size);
   if (!alsa_bufdata) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
      goto Error;
   }

   /* Initialise mixer. */
   digi_alsa.voices = voices;

   if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate,
		   alsa_stereo, ((alsa_bits == 16) ? 1 : 0),
		   &digi_alsa.voices) != 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
      goto Error;
   }

   snd_pcm_prepare(pcm_handle);
   pdc = snd_pcm_poll_descriptors_count (pcm_handle);
   if (pdc <= 0) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count"));
      goto Error;
   }

   ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc);
   if (ufds == NULL) {
      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors"));
      goto Error;
   }
   ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc));

   poll_next = 0;

   _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);

   /* Add audio interrupt. */
   _unix_bg_man->register_func(alsa_update);

   uszprintf(alsa_desc, sizeof(alsa_desc),
	     get_config_text
	     ("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"),
	     alsa_device, alsa_bits,
	     uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1),
	     alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2));

   digi_driver->desc = alsa_desc;
   return 0;

 Error:
   if (pcm_handle) {
      snd_pcm_close(pcm_handle);
      pcm_handle = NULL;
   }

   return -1;
}