コード例 #1
0
ファイル: kcm_instance.c プロジェクト: sesc4mt/mvcdecoder
/* Function: al_set_sample_instance_playing
 */
bool al_set_sample_instance_playing(ALLEGRO_SAMPLE_INSTANCE *spl, bool val)
{
    ASSERT(spl);

    if (!spl->parent.u.ptr) {
        _al_set_error(ALLEGRO_INVALID_OBJECT, "Sample has no parent");
        return false;
    }
    if (!spl->spl_data.buffer.ptr) {
        _al_set_error(ALLEGRO_INVALID_OBJECT, "Sample has no data");
        return false;
    }

    if (spl->parent.is_voice) {
        /* parent is voice */
        ALLEGRO_VOICE *voice = spl->parent.u.voice;

        return al_set_voice_playing(voice, val);
    }

    /* parent is mixer */
    maybe_lock_mutex(spl->mutex);
    spl->is_playing = val;
    if (!val)
        spl->pos = 0;
    maybe_unlock_mutex(spl->mutex);
    return true;
}
コード例 #2
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_set_audio_stream_fragment
 */
bool al_set_audio_stream_fragment(ALLEGRO_AUDIO_STREAM *stream, void *val)
{
   size_t i;
   bool ret;
   ALLEGRO_MUTEX *stream_mutex;
   ASSERT(stream);

   stream_mutex = maybe_lock_mutex(stream->spl.mutex);

   for (i = 0; i < stream->buf_count && stream->pending_bufs[i] ; i++)
      ;
   if (i < stream->buf_count) {
      stream->pending_bufs[i] = val;
      ret = true;
   }
   else {
      _al_set_error(ALLEGRO_INVALID_OBJECT,
         "Attempted to set a stream buffer with a full pending list");
      ret = false;
   }

   maybe_unlock_mutex(stream_mutex);

   return ret;
}
コード例 #3
0
/* Function: al_set_sample_instance_gain
 */
bool al_set_sample_instance_gain(ALLEGRO_SAMPLE_INSTANCE *spl, float val)
{
   ASSERT(spl);

   if (spl->parent.u.ptr && spl->parent.is_voice) {
      _al_set_error(ALLEGRO_GENERIC_ERROR,
         "Could not set gain of sample attached to voice");
      return false;
   }

   if (spl->gain != val) {
      spl->gain = val;

      /* If attached to a mixer already, need to recompute the sample
       * matrix to take into account the gain.
       */
      if (spl->parent.u.mixer) {
         ALLEGRO_MIXER *mixer = spl->parent.u.mixer;

         maybe_lock_mutex(spl->mutex);
         _al_kcm_mixer_rejig_sample_matrix(mixer, spl);
         maybe_unlock_mutex(spl->mutex);
      }
   }

   return true;
}
コード例 #4
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_set_audio_stream_pan
 */
bool al_set_audio_stream_pan(ALLEGRO_AUDIO_STREAM *stream, float val)
{
   ASSERT(stream);

   if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
      _al_set_error(ALLEGRO_GENERIC_ERROR,
         "Could not set gain of stream attached to voice");
      return false;
   }
   if (val != ALLEGRO_AUDIO_PAN_NONE && (val < -1.0 || val > 1.0)) {
      _al_set_error(ALLEGRO_GENERIC_ERROR, "Invalid pan value");
      return false;
   }

   if (stream->spl.pan != val) {
      stream->spl.pan = val;

      /* If attached to a mixer already, need to recompute the sample
       * matrix to take into account the panning.
       */
      if (stream->spl.parent.u.mixer) {
         ALLEGRO_MIXER *mixer = stream->spl.parent.u.mixer;
         ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
         _al_kcm_mixer_rejig_sample_matrix(mixer, &stream->spl);
         maybe_unlock_mutex(stream_mutex);
      }
   }

   return true;
}
コード例 #5
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_set_audio_stream_playing
 */
bool al_set_audio_stream_playing(ALLEGRO_AUDIO_STREAM *stream, bool val)
{
   bool rc = true;
   ALLEGRO_MUTEX *stream_mutex;
   ASSERT(stream);

   if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
      ALLEGRO_VOICE *voice = stream->spl.parent.u.voice;
      if (val != stream->spl.is_playing) {
         rc = _al_kcm_set_voice_playing(voice, voice->mutex, val);
      }
   }

   stream_mutex = maybe_lock_mutex(stream->spl.mutex);

   stream->spl.is_playing = rc && val;

   if (stream->spl.is_playing) {
      /* We usually emit fragment events when a fragment is used up, but if the
       * stream has zero pending fragments to begin with then no events would
       * ever be emitted.
       */
      _al_kcm_emit_stream_events(stream);
   }
   else if (!val) {
      reset_stopped_stream(stream);
   }

   maybe_unlock_mutex(stream_mutex);

   return rc;
}
コード例 #6
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_set_audio_stream_speed
 */
bool al_set_audio_stream_speed(ALLEGRO_AUDIO_STREAM *stream, float val)
{
   ASSERT(stream);

   if (val <= 0.0f) {
      _al_set_error(ALLEGRO_INVALID_PARAM,
         "Attempted to set stream speed to a zero or negative value");
      return false;
   }

   if (stream->spl.parent.u.ptr && stream->spl.parent.is_voice) {
      _al_set_error(ALLEGRO_GENERIC_ERROR,
         "Could not set voice playback speed");
      return false;
   }

   stream->spl.speed = val;
   if (stream->spl.parent.u.mixer) {
      ALLEGRO_MIXER *mixer = stream->spl.parent.u.mixer;
      ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);

      stream->spl.step = (stream->spl.spl_data.frequency) * stream->spl.speed;
      stream->spl.step_denom = mixer->ss.spl_data.frequency;
      /* Don't wanna be trapped with a step value of 0 */
      if (stream->spl.step == 0) {
         stream->spl.step = 1;
      }

      maybe_unlock_mutex(stream_mutex);
   }

   return true;
}
コード例 #7
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_get_audio_stream_fragment
*/
void *al_get_audio_stream_fragment(const ALLEGRO_AUDIO_STREAM *stream)
{
   size_t i;
   void *fragment;
   ALLEGRO_MUTEX *stream_mutex;
   ASSERT(stream);

   stream_mutex = maybe_lock_mutex(stream->spl.mutex);

   if (!stream->used_bufs[0]) {
      /* No free fragments are available. */
      fragment = NULL;
   }
   else {
      fragment = stream->used_bufs[0];
      for (i = 0; i < stream->buf_count-1 && stream->used_bufs[i]; i++) {
         stream->used_bufs[i] = stream->used_bufs[i+1];
      }
      stream->used_bufs[i] = NULL;
   }

   maybe_unlock_mutex(stream_mutex);

   return fragment;
}
コード例 #8
0
/* Function: al_set_sample_instance_pan
 */
bool al_set_sample_instance_pan(ALLEGRO_SAMPLE_INSTANCE *spl, float val)
{
   ASSERT(spl);

   if (spl->parent.u.ptr && spl->parent.is_voice) {
      _al_set_error(ALLEGRO_GENERIC_ERROR,
         "Could not set panning of sample attached to voice");
      return false;
   }
   if (val != ALLEGRO_AUDIO_PAN_NONE && (val < -1.0 || val > 1.0)) {
      _al_set_error(ALLEGRO_GENERIC_ERROR, "Invalid pan value");
      return false;
   }

   if (spl->pan != val) {
      spl->pan = val;

      /* If attached to a mixer already, need to recompute the sample
       * matrix to take into account the panning.
       */
      if (spl->parent.u.mixer) {
         ALLEGRO_MIXER *mixer = spl->parent.u.mixer;

         maybe_lock_mutex(spl->mutex);
         _al_kcm_mixer_rejig_sample_matrix(mixer, spl);
         maybe_unlock_mutex(spl->mutex);
      }
   }

   return true;
}
コード例 #9
0
/* Function: al_set_sample_instance_playmode
 */
bool al_set_sample_instance_playmode(ALLEGRO_SAMPLE_INSTANCE *spl,
   ALLEGRO_PLAYMODE val)
{
   ASSERT(spl);

   if (val < ALLEGRO_PLAYMODE_ONCE || val > ALLEGRO_PLAYMODE_BIDIR) {
      _al_set_error(ALLEGRO_INVALID_PARAM,
         "Invalid loop mode");
      return false;
   }

   maybe_lock_mutex(spl->mutex);

   spl->loop = val;
   if (spl->loop != ALLEGRO_PLAYMODE_ONCE) {
      if (spl->pos < spl->loop_start)
         spl->pos = spl->loop_start;
      else if (spl->pos > spl->loop_end-1)
         spl->pos = spl->loop_end-1;
   }

   maybe_unlock_mutex(spl->mutex);

   return true;
}
コード例 #10
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_seek_audio_stream_secs
 */
bool al_seek_audio_stream_secs(ALLEGRO_AUDIO_STREAM *stream, double time)
{
   bool ret;

   if (stream->seek_feeder) {
      ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
      ret = stream->seek_feeder(stream, time);
      maybe_unlock_mutex(stream_mutex);
      return ret;
   }

   return false;
}
コード例 #11
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_get_audio_stream_length_secs
 */
double al_get_audio_stream_length_secs(ALLEGRO_AUDIO_STREAM *stream)
{
   double ret;

   if (stream->get_feeder_length) {
      ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
      ret = stream->get_feeder_length(stream);
      maybe_unlock_mutex(stream_mutex);
      return ret;
   }

   return 0.0;
}
コード例 #12
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_rewind_audio_stream
 */
bool al_rewind_audio_stream(ALLEGRO_AUDIO_STREAM *stream)
{
   bool ret;

   if (stream->rewind_feeder) {
      ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
      ret = stream->rewind_feeder(stream);
      maybe_unlock_mutex(stream_mutex);
      return ret;
   }

   return false;
}
コード例 #13
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_set_audio_stream_loop_secs
 */
bool al_set_audio_stream_loop_secs(ALLEGRO_AUDIO_STREAM *stream,
   double start, double end)
{
   bool ret;

   if (start >= end)
      return false;

   if (stream->set_feeder_loop) {
      ALLEGRO_MUTEX *stream_mutex = maybe_lock_mutex(stream->spl.mutex);
      ret = stream->set_feeder_loop(stream, start, end);
      maybe_unlock_mutex(stream_mutex);
      return ret;
   }

   return false;
}
コード例 #14
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* Function: al_get_audio_stream_played_samples
*/
uint64_t al_get_audio_stream_played_samples(const ALLEGRO_AUDIO_STREAM *stream)
{
   uint64_t result;
   ALLEGRO_MUTEX *stream_mutex;
   ASSERT(stream);

   stream_mutex = maybe_lock_mutex(stream->spl.mutex);
   if (stream->spl.spl_data.buffer.ptr) {
      result = stream->consumed_fragments * stream->spl.spl_data.len +
         stream->spl.pos;
   }
   else {
      result = 0;
   }
   maybe_unlock_mutex(stream_mutex);

   return result;
}
コード例 #15
0
/* Function: al_set_sample_instance_position
 */
bool al_set_sample_instance_position(ALLEGRO_SAMPLE_INSTANCE *spl,
   unsigned int val)
{
   ASSERT(spl);

   if (spl->parent.u.ptr && spl->parent.is_voice) {
      ALLEGRO_VOICE *voice = spl->parent.u.voice;
      if (!al_set_voice_position(voice, val))
         return false;
   }
   else {
      maybe_lock_mutex(spl->mutex);
      spl->pos = val;
      maybe_unlock_mutex(spl->mutex);
   }

   return true;
}
コード例 #16
0
ファイル: kcm_instance.c プロジェクト: sesc4mt/mvcdecoder
/* _al_kcm_detach_from_parent:
 *  This detaches the sample, stream, or mixer from anything it may be attached
 *  to.
 */
void _al_kcm_detach_from_parent(ALLEGRO_SAMPLE_INSTANCE *spl)
{
    ALLEGRO_MIXER *mixer;
    int i;

    if (!spl || !spl->parent.u.ptr)
        return;

    if (spl->parent.is_voice) {
        al_detach_voice(spl->parent.u.voice);
        return;
    }

    mixer = spl->parent.u.mixer;

    /* Search through the streams and check for this one */
    for (i = _al_vector_size(&mixer->streams) - 1; i >= 0; i--) {
        ALLEGRO_SAMPLE_INSTANCE **slot = _al_vector_ref(&mixer->streams, i);

        if (*slot == spl) {
            maybe_lock_mutex(mixer->ss.mutex);

            _al_vector_delete_at(&mixer->streams, i);
            spl->parent.u.mixer = NULL;
            _al_kcm_stream_set_mutex(spl, NULL);

            if (spl->spl_read != _al_kcm_mixer_read)
                spl->spl_read = NULL;

            maybe_unlock_mutex(mixer->ss.mutex);

            break;
        }
    }

    free(spl->matrix);
    spl->matrix = NULL;
}
コード例 #17
0
/* Function: al_set_sample_instance_speed
 */
bool al_set_sample_instance_speed(ALLEGRO_SAMPLE_INSTANCE *spl, float val)
{
   ASSERT(spl);

   if (fabsf(val) < (1.0f/64.0f)) {
      _al_set_error(ALLEGRO_INVALID_PARAM,
         "Attempted to set zero speed");
      return false;
   }

   if (spl->parent.u.ptr && spl->parent.is_voice) {
      _al_set_error(ALLEGRO_GENERIC_ERROR,
         "Could not set voice playback speed");
      return false;
   }

   spl->speed = val;
   if (spl->parent.u.mixer) {
      ALLEGRO_MIXER *mixer = spl->parent.u.mixer;

      maybe_lock_mutex(spl->mutex);

      spl->step = (spl->spl_data.frequency) * spl->speed;
      spl->step_denom = mixer->ss.spl_data.frequency;
      /* Don't wanna be trapped with a step value of 0 */
      if (spl->step == 0) {
         if (spl->speed > 0.0f)
            spl->step = 1;
         else
            spl->step = -1;
      }

      maybe_unlock_mutex(spl->mutex);
   }

   return true;
}
コード例 #18
0
ファイル: kcm_stream.c プロジェクト: ReganChetty/allegro5
/* _al_kcm_feed_stream:
 * A routine running in another thread that feeds the stream buffers as
 * neccesary, usually getting data from some file reader backend.
 */
void *_al_kcm_feed_stream(ALLEGRO_THREAD *self, void *vstream)
{
   ALLEGRO_AUDIO_STREAM *stream = vstream;
   ALLEGRO_EVENT_QUEUE *queue;
   ALLEGRO_EVENT event;
   (void)self;

   ALLEGRO_DEBUG("Stream feeder thread started.\n");

   queue = al_create_event_queue();
   al_register_event_source(queue, &stream->spl.es);

   al_lock_mutex(stream->feed_thread_started_mutex);
   stream->feed_thread_started = true;
   al_broadcast_cond(stream->feed_thread_started_cond);
   al_unlock_mutex(stream->feed_thread_started_mutex);

   stream->quit_feed_thread = false;

   while (!stream->quit_feed_thread) {
      char *fragment;
      ALLEGRO_EVENT event;

      al_wait_for_event(queue, &event);

      if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT
          && !stream->is_draining) {
         unsigned long bytes;
         unsigned long bytes_written;
         ALLEGRO_MUTEX *stream_mutex;

         fragment = al_get_audio_stream_fragment(stream);
         if (!fragment) {
            /* This is not an error. */
            continue;
         }

         bytes = (stream->spl.spl_data.len) *
               al_get_channel_count(stream->spl.spl_data.chan_conf) *
               al_get_audio_depth_size(stream->spl.spl_data.depth);

         stream_mutex = maybe_lock_mutex(stream->spl.mutex);
         bytes_written = stream->feeder(stream, fragment, bytes);
         maybe_unlock_mutex(stream_mutex);

         if (stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONEDIR) {
            /* Keep rewinding until the fragment is filled. */
            while (bytes_written < bytes &&
                     stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONEDIR) {
               size_t bw;
               al_rewind_audio_stream(stream);
               stream_mutex = maybe_lock_mutex(stream->spl.mutex);
               bw = stream->feeder(stream, fragment + bytes_written,
                  bytes - bytes_written);
               bytes_written += bw;
               maybe_unlock_mutex(stream_mutex);
            }
         }
         else if (bytes_written < bytes) {
            /* Fill the rest of the fragment with silence. */
            int silence_samples = (bytes - bytes_written) /
               (al_get_channel_count(stream->spl.spl_data.chan_conf) *
                al_get_audio_depth_size(stream->spl.spl_data.depth));
            al_fill_silence(fragment + bytes_written, silence_samples,
                            stream->spl.spl_data.depth, stream->spl.spl_data.chan_conf);
         }

         if (!al_set_audio_stream_fragment(stream, fragment)) {
            ALLEGRO_ERROR("Error setting stream buffer.\n");
            continue;
         }

         /* The streaming source doesn't feed any more, drain buffers and quit. */
         if (bytes_written != bytes &&
            stream->spl.loop == _ALLEGRO_PLAYMODE_STREAM_ONCE) {
            al_drain_audio_stream(stream);
            stream->quit_feed_thread = true;
         }
      }
      else if (event.type == _KCM_STREAM_FEEDER_QUIT_EVENT_TYPE) {
         stream->quit_feed_thread = true;
      }
   }
   
   event.user.type = ALLEGRO_EVENT_AUDIO_STREAM_FINISHED;
   event.user.timestamp = al_get_time();
   al_emit_user_event(&stream->spl.es, &event, NULL);

   al_destroy_event_queue(queue);

   ALLEGRO_DEBUG("Stream feeder thread finished.\n");

   return NULL;
}