Ejemplo n.º 1
0
size_t
sound_unqueue_buffers (ALuint source, SoundNameCallback callback,
		       void *user_data)
{
  ALint count;
  ALuint buf;
  size_t removed = 0;

  alGetSourcei (source, AL_BUFFERS_PROCESSED, &count);
  if (!check_al ("alGetSourcei (AL_BUFFERS_PROCESSED)"))
    return 0;

  while (count-- > 0)
    {
      alSourceUnqueueBuffers (source, 1, &buf);
      if (!check_al ("alSourceUnqueueBuffers"))
	return removed;

      if (callback != NULL)
	callback (buf, user_data);

      removed++;
    }

  return removed;
}
Ejemplo n.º 2
0
void
sound_delete_source_and_buffers (ALuint source)
{
  alSourceStop (source);
  check_al ("alSourceStop");

  sound_unqueue_buffers (source,
			 (SoundNameCallback) delete_queued_buffer, NULL);

  alDeleteSources (1, &source);
  check_al ("alDeleteSources");
}
Ejemplo n.º 3
0
// Set wav volume
//
// <int> vol = wav volume, 0-100
//
void OpenALAudio::set_wav_volume(int vol)
{
   StreamMap::const_iterator itr;
   float gain;
   float gain_mult;
   int diff;

   if (!this->wav_init_flag)
      return;

   MSG("set_wav_volume(%i)\n", vol);

   vol = MAX(vol, 0);
   vol = MIN(vol, 100);
   vol = vol * 100 - 10000;
   diff = vol - this->wav_volume;
   gain_mult = millibels_to_ratio(diff);

   for (itr = this->streams.begin(); itr != this->streams.end(); ++itr)
   {
      alGetSourcef(itr->second->source, AL_GAIN, &gain);
      alSourcef(itr->second->source, AL_GAIN, gain * gain_mult);
      check_al();
   }

   this->wav_volume = vol;
}
Ejemplo n.º 4
0
static void
unqueue_source_buffers (SourceDescriptor *src)
{
  SoundSample *s;

  if (src->buffers_used == 0)
    return;

  s = src->sample;

  src->buffers_used -=
    sound_unqueue_buffers (src->name,
			   (SoundNameCallback) push_free_buffer,
			   NULL);

  if (src->buffers_used > 0
      || s->pos[s->current_buffer] < s->len[s->current_buffer]
      || s->loop_count == 0)
    return;

  /* this check prevents the sound in the intro from abruptly stopping */
  if (!s->done[0] && !s->done[1])
    return;

  alSourceStop (src->name);
  check_al ("alSourceStop");
  s->status = 2;
}
Ejemplo n.º 5
0
static bool
create_sources (void)
{
  size_t n, m;
  ALuint source;
  ALuint buffers[SOUND_BUFFERS_PER_SRC];

  for (n = 0; n < SOUND_MUSIC_BUFFERS; n++)
    {
      alGenBuffers (1, &buffers[0]);
      if (!check_al ("alGenBuffers"))
	goto err;

      push_free_buffer (buffers[0]);
    }

  for (n = 0; n < SOUND_MAX_SOURCES; n++)
    {
      alGenSources (1, &source);
      if (alGetError () != AL_NO_ERROR)
	{
	  n--;
	  break;
	}

      alGenBuffers (SOUND_BUFFERS_PER_SRC, buffers);
      if (alGetError () != AL_NO_ERROR)
	{
	  sound_delete_source_and_buffers (source);
	  n--;
	  break;
	}

      initialise_descriptor (sound_source_count++, source);

      for (m = 0; m < SOUND_BUFFERS_PER_SRC; m++)
	push_free_buffer (buffers[m]);
    }

  if (sound_source_count == 0)
    {
      fprintf (stderr, "Error: OpenAL: "
	               "Failed to create sound sources.\n");
      goto err;
    }

#ifdef ENABLE_DEBUG
  printf ("OpenAL: Created %zu sound sources.\n", sound_source_count);
#endif

  return true;

err:
  /* TODO: clean up */
  return false;
}
Ejemplo n.º 6
0
bool OpenALAudio::StreamContext::init(AudioStream *as)
{
   if (this->source != 0)
      return false;

   alGenSources(1, &this->source);
   if (!check_al())
      goto err;

   this->stream = as;

   return true;

err:
   return false;
}
Ejemplo n.º 7
0
static void
destroy_sources (void)
{
  size_t n;

  for (n = 0; n < SOUND_MAX_SOURCES; n++)
    {
      if (sound_sources[n].name == 0)
	continue;

      sound_delete_source_and_buffers (sound_sources[n].name);
    }

  alDeleteBuffers (sound_free_buffer_count, sound_free_buffers);
  check_al ("alDeleteBuffers");
}
Ejemplo n.º 8
0
/* Changes the volume/panning of a wave.  Does not attenuate by wav_volume. */
void OpenALAudio::volume_long_wav(int id, const DsVolume &vol)
{
   StreamContext *sc;
   StreamMap::const_iterator itr;

   if (!this->wav_init_flag)
      return;

   MSG("volume_long_wav(%i, (%li, %li))\n", id, vol.ds_vol, vol.ds_pan);

   itr = this->streams.find(id);
   if (itr == this->streams.end())
      return;

   sc = itr->second;
   set_source_volume(sc->source, vol.ds_vol);
   set_source_panning(sc->source, vol.ds_pan);
   check_al();
}
Ejemplo n.º 9
0
/*
 * in  - wav file stream to play.  Claims ownership and will delete it.
 * vol - volume/panning
 *
 * return: 1 on success, 0 on failure
 */
int OpenALAudio::play_long_wav(InputStream *in, const DsVolume &vol)
{
   const int BUFFER_COUNT = 4;

   StreamContext *sc = NULL;
   WavStream *ws = NULL;
   int id;

   assert(this->wav_init_flag);

   ws = new WavStream;
   if (!ws->open(in))
   {
      delete in;
      goto err;
   }

   sc = new StreamContext;

   if (!sc->init(ws))
      goto err;

   set_source_panning(sc->source, vol.ds_pan);
   set_source_volume(sc->source, vol.ds_vol + this->wav_volume);

   if (!check_al())
      goto err;

   sc->stream_data(BUFFER_COUNT);

   id = unused_key(&this->streams);
   this->streams[id] = sc;

   return id;

err:
   delete sc;
   delete ws;
   return 0;
}
Ejemplo n.º 10
0
bool OpenALAudio::StreamContext::stream_data(int new_buffer_count)
{
   const size_t BUFFER_SIZE = 0x4000;

   /*
    * This constant determines how many milliseconds of audio data go into
    * one buffer.  The larger it is, the less probability of skipping, but
    * the longer the delay from calling stop() to the point when it
    * actually stops.
    */
   const size_t MAX_BUFFER_TIME_MS = 50;

   uint8_t data[BUFFER_SIZE];
   size_t frames_read;
   size_t max_frames;
   ALenum format;
   ALuint buf;
   ALint state;

   if (!this->streaming)
      return false;

   format = openal_format(this->stream);
   max_frames = this->stream->frame_rate() * MAX_BUFFER_TIME_MS / 1000;

   for (;;)
   {
      buf = 0;

      if (new_buffer_count > 0)
      {
	 alGenBuffers(1, &buf);
	 if (!check_al())
	    goto err;

	 new_buffer_count--;
      }
      else
      {
	 ALint processed;

	 alGetSourcei(this->source, AL_BUFFERS_PROCESSED, &processed);

	 if (processed == 0)
	    break;

	 alSourceUnqueueBuffers(this->source, 1, &buf);
	 if (!check_al())
	    goto err;
      }

      size_t space_frames = sizeof(data) / this->stream->frame_size();
      space_frames = MIN(space_frames, max_frames);
      frames_read = this->stream->read(data, space_frames);

      if (frames_read == 0)
      {
	 if (this->looping)
	 {
	    this->stream->seek(this->loop_start_frame);
	    frames_read = this->stream->read(data, space_frames);
	    if (frames_read == 0)
	    {
	       this->streaming = false;
	       break;
	    }
	 }
	 else
	 {
	    this->streaming = false;
	    break;
	 }
      }

      if (this->fade_frames != 0)
	 this->apply_fading(data, frames_read);

      alBufferData(buf, format, data,
		   frames_read * this->stream->frame_size(),
		   this->stream->frame_rate());
      if (!check_al())
	 goto err;

      alSourceQueueBuffers(this->source, 1, &buf);
      if (!check_al())
	 goto err;
   }

   if (!this->streaming)
   {
      alDeleteBuffers(1, &buf);
      check_al();
   }

   alGetSourcei(this->source, AL_SOURCE_STATE, &state);

   if (state != AL_PLAYING)
   {
      alSourcePlay(this->source);
      check_al();
   }

   return this->streaming;

err:
   if (buf != 0)
      alDeleteBuffers(1, &buf);

   this->streaming = false;
   return false;
}
Ejemplo n.º 11
0
static void
delete_queued_buffer (ALuint buf)
{
  alDeleteBuffers (1, &buf);
  check_al ("alDeleteBuffers");
}
Ejemplo n.º 12
0
static void
queue_source_buffers (SoundPCMDriver *pcmdrv, SourceDescriptor *src)
{
  size_t len, total_len;
  void *data;
  float x_pos;
  ALint state;
  SoundSample *s;
  ALuint buf = 0;

  if (src->buffers_used >= SOUND_BUFFERS_PER_SRC)
    return;

  s = src->sample;

  total_len = s->len[s->current_buffer] - s->pos[s->current_buffer];

  if (total_len == 0)
    {
      if (s->done[s->current_buffer ^ 1] == 0)
	s->current_buffer ^= 1;
      else
	return;

      total_len = s->len[s->current_buffer] - s->pos[s->current_buffer];
    }


  while (total_len > 0 && src->buffers_used < SOUND_BUFFERS_PER_SRC)
    {
      data = s->start[s->current_buffer] + s->pos[s->current_buffer];
      len = MIN (total_len, SOUND_MAX_BUFSIZE);

      assert ((s->flags & 1) != 0);

      buf = pop_free_buffer ();
      alBufferData (buf, get_pcm_format (s), data, len, s->playback_rate);
      if (!check_al ("alBufferData"))
	goto err;

      alSourceQueueBuffers (src->name, 1, &buf);
      if (!check_al ("alSourceQueueBuffers"))
	goto err;

      src->buffers_used++;

      alGetSourcei (src->name, AL_SOURCE_STATE, &state);
      if (!check_al ("alGetSourcei (AL_SOURCE_STATE)"))
	goto err;

      alSourcef (src->name, AL_GAIN,
		 (s->volume * (1.f / 127.f)
		  * (pcmdrv->master_volume * (1.f / 127.f))));
      if (!check_al ("alSourcef (AL_GAIN)"))
	goto err;

      /* XXX: check if panning/position is OK */
      if (s->pan == 0)
	x_pos = 0.f;
      else
	x_pos = (127 - s->pan - 64) * (1.f / 64.f);

      alSource3f (src->name, AL_POSITION, x_pos, 0.f, -.25f);
      if (!check_al ("alSource3f (AL_POSITION)"))
	goto err;

      if (state != AL_PLAYING)
	{
	  alSourcePlay (src->name);
	  if (!check_al ("alSourcePlay"))
	    goto err;
	}

      s->pos[s->current_buffer] += len;
      total_len -= len;

      if (total_len == 0 && s->loop_count == 0)
	{
	  s->pos[s->current_buffer] = 0;
	  total_len = s->len[s->current_buffer] - s->pos[s->current_buffer];
	}
    }

  return;

err:
  if (buf != 0)
    push_free_buffer (buf);
}