示例#1
0
/** @internal @This handles input.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to upump structure
 */
static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref,
                                       struct upump **upump_p)
{
    struct upipe_filter_ebur128 *upipe_filter_ebur128 =
                                 upipe_filter_ebur128_from_upipe(upipe);
    double loud = 0, lra = 0, global = 0;
    size_t samples;
    if (unlikely(!ubase_check(uref_sound_size(uref, &samples, NULL)))) {
        upipe_warn(upipe, "invalid sound buffer");
        uref_free(uref);
        return;
    }
    const char *channel = NULL;
    const int16_t *buf = NULL;
    if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) {
        if (unlikely(!ubase_check(uref_sound_plane_read_int16_t(uref,
                channel, 0, -1, &buf)))) {
            upipe_warn(upipe, "error mapping sound buffer");
            uref_free(uref);
            return;
        }

        if (unlikely((uintptr_t)buf & 1)) {
            upipe_warn(upipe, "unaligned buffer");
        }
        ebur128_add_frames_short(upipe_filter_ebur128->st, buf, samples);
        uref_sound_plane_unmap(uref, channel, 0, -1);
    }
    ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud);
    ebur128_loudness_range(upipe_filter_ebur128->st, &lra);
    ebur128_loudness_global(upipe_filter_ebur128->st, &global);

    uref_ebur128_set_momentary(uref, loud);
    uref_ebur128_set_lra(uref, lra);
    uref_ebur128_set_global(uref, global);

    upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global);

    upipe_filter_ebur128_output(upipe, uref, upump_p);
}
示例#2
0
/** @internal @This handles input.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to upump structure
 */
static void upipe_filter_ebur128_input(struct upipe *upipe, struct uref *uref,
                                       struct upump **upump_p)
{
    struct upipe_filter_ebur128 *upipe_filter_ebur128 =
                                 upipe_filter_ebur128_from_upipe(upipe);
    double loud = 0, lra = 0, global = 0;

    if (unlikely(upipe_filter_ebur128->output_flow == NULL)) {
        upipe_err_va(upipe, "invalid input");
        uref_free(uref);
        return;
    }

    size_t samples;
    uint8_t sample_size;
    if (unlikely(!ubase_check(uref_sound_size(uref, &samples, &sample_size)))) {
        upipe_warn(upipe, "invalid sound buffer");
        uref_free(uref);
        return;
    }

    void *buf = NULL;
    const char *channel = NULL;
    if (upipe_filter_ebur128->planes == 1) {
        if (ubase_check(uref_sound_plane_iterate(uref, &channel)) && channel) {
            if (unlikely(!ubase_check(uref_sound_plane_read_void(uref,
                    channel, 0, -1, (const void **)&buf)))) {
                upipe_warn(upipe, "error mapping sound buffer");
                uref_free(uref);
                return;
            }
        }

    } else {
        buf = malloc(sample_size * upipe_filter_ebur128->channels * samples);
        if (buf == NULL) {
            upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
            uref_free(uref);
            return;
        }
        if (!ubase_check(uref_sound_interleave(uref, (uint8_t *)buf, 0,
                                               samples, sample_size,
                                               upipe_filter_ebur128->planes))) {
            upipe_warn(upipe, "error mapping sound buffer");
            uref_free(uref);
            return;
        }
    }

    if (unlikely((uintptr_t)buf & 1))
        upipe_warn(upipe, "unaligned buffer");

    switch (upipe_filter_ebur128->fmt) {
        case UPIPE_FILTER_EBUR128_SHORT:
            ebur128_add_frames_short(upipe_filter_ebur128->st, (short *)buf,
                                     samples);
            break;

        case UPIPE_FILTER_EBUR128_INT:
            ebur128_add_frames_int(upipe_filter_ebur128->st, (int *)buf,
                                   samples);
            break;

        case UPIPE_FILTER_EBUR128_FLOAT:
            ebur128_add_frames_float(upipe_filter_ebur128->st, (float *)buf,
                                     samples);
            break;

        case UPIPE_FILTER_EBUR128_DOUBLE:
            ebur128_add_frames_double(upipe_filter_ebur128->st, (double *)buf,
                                      samples);
            break;

        default:
            upipe_warn_va(upipe, "unknown sample format %d",
                          upipe_filter_ebur128->fmt);
            break;
    }

    if (upipe_filter_ebur128->planes == 1)
        uref_sound_plane_unmap(uref, channel, 0, -1);
    else
        free(buf);

    ebur128_loudness_momentary(upipe_filter_ebur128->st, &loud);
    ebur128_loudness_range(upipe_filter_ebur128->st, &lra);
    ebur128_loudness_global(upipe_filter_ebur128->st, &global);

    uref_ebur128_set_momentary(uref, loud);
    uref_ebur128_set_lra(uref, lra);
    uref_ebur128_set_global(uref, global);

    upipe_verbose_va(upipe, "loud %f lra %f global %f", loud, lra, global);

    upipe_filter_ebur128_output(upipe, uref, upump_p);
}
示例#3
0
文件: shusherd.c 项目: shyPi/shyPi
void audio_trigger(context_t *context) {
  int input_fd = -1;
  static const pa_sample_spec ss = {
    .format = PA_SAMPLE_S16LE,
    .rate = 44100,
    .channels = 1
  };
  int error;

  daemon_log(LOG_INFO, "Trigger %s", context->shush_filename);

  if (context->points_threshold < 0) {
    daemon_log(LOG_INFO, "Threshold below 0, not triggering sound");
  }

  daemon_log(LOG_INFO,
             "Opening %s for output",
             context->output_device ?: "default sink");

  pa_simple *pa_output = pa_simple_new(
                              NULL,
                              "shusherd",
                              PA_STREAM_PLAYBACK,
                              context->output_device,
                              "playback",
                              &ss,
                              NULL,
                              NULL,
                              &error);
  if (!pa_output) {
    daemon_log(LOG_ERR, "pa_simple_new failed: %s", pa_strerror(error));
    goto finish;
  }

  input_fd = open(context->shush_filename, O_RDONLY);
  if (input_fd < 0) {
    daemon_log(LOG_ERR, "Error reading %s: %s", context->shush_filename, strerror(errno));
    goto finish;
  }

  for (;;) {
    uint8_t buf[BUFSIZE];
    ssize_t r;

    r = read(input_fd, buf, sizeof(buf));
    if (r < 0) {
      daemon_log(LOG_ERR, "read() failed: %s", strerror(errno));
      goto finish;
    }

    if (r == 0)
      goto finish;

    if (pa_simple_write(pa_output, buf, (size_t) r, &error) < 0) {
      daemon_log(LOG_ERR, "pa_simple_write() failed: %s", pa_strerror(errno));
      goto finish;
    }
  }

  if (pa_simple_drain(pa_output, &error) < 0) {
    daemon_log(LOG_ERR, "pa_simple_drain() failed: %s", pa_strerror(errno));
    goto finish;
  }

finish:
  if (input_fd > 0)
    close(input_fd);
  if (pa_output)
    pa_simple_free(pa_output);
}

void *audio_loop(void *context_p) {
  context_t *context = (context_t *)context_p;
  time_t t = time(NULL);
  double loudness;
  double points = 0.0;
  int error;

  //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

  daemon_log(LOG_INFO, "Starting listening...");

  const short buf[BUFSIZE/2];

  int bytes = 0;
  int trigger = 0;
  int latest_trigger_time = 0;

  while (context->enable_processing) {
    if ((bytes = pa_simple_read(context->pa_input, (void *)buf, sizeof(buf), &error)) < 0) {
      daemon_log(LOG_ERR, "pa_simple_read failed: %s", pa_strerror(error));
      assert(0);
    }

    if ((time(NULL) - latest_trigger_time) < context->cooldown) {
      continue;
    }

    ebur128_add_frames_short(context->ebur128_state, buf, sizeof(buf)/2);

    if ((time(NULL) - t) > SAMPLE_TIME) {
      t = time(NULL);
      ebur128_loudness_shortterm(context->ebur128_state, &loudness);

      points += 100 - fabs(loudness);

      daemon_log(LOG_INFO, "Points: %f (%d) (%f)",
                 points, context->points_threshold, loudness);

      if (points > context->points_threshold) {
        trigger = 1;
      } else {
        points *= context->decay;
      }
    }

    if (trigger) {
      latest_trigger_time = time(NULL);
      audio_trigger(context);
      points = 0;
      trigger = 0;
      daemon_log(LOG_INFO,
                 "Waiting %d seconds before listening again",
                 context->cooldown);
    }
  }

  daemon_log(LOG_INFO, "Stopped listening...");

  return 0;
}