Пример #1
0
/* Called from main context */
pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
    pa_source_output_assert_ref(o);
    pa_assert_ctl_context();

    if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
        pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
        return usec;
    }

    /* If this source output is not realized yet or is being moved, we
     * have to touch the thread info data directly */

    if (o->source) {
        if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
            usec = pa_source_get_fixed_latency(o->source);

        if (usec != (pa_usec_t) -1) {
            pa_usec_t min_latency, max_latency;
            pa_source_get_latency_range(o->source, &min_latency, &max_latency);
            usec = PA_CLAMP(usec, min_latency, max_latency);
        }
    }

    o->thread_info.requested_source_latency = usec;

    return usec;
}
/* Called from main context */
static void adjust_rates(struct userdata *u) {
    size_t buffer, fs;
    uint32_t old_rate, base_rate, new_rate;
    pa_usec_t buffer_latency;

    pa_assert(u);
    pa_assert_ctl_context();

    pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
    pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);

    buffer =
        u->latency_snapshot.sink_input_buffer +
        u->latency_snapshot.source_output_buffer;

    if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter)
        buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter);
    else
        buffer += PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter));

    buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec);

    pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",
                (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC,
                (double) buffer_latency / PA_USEC_PER_MSEC,
                (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,
                ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC);

    pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes",
                u->latency_snapshot.max_request*2,
                u->latency_snapshot.min_memblockq_length);

    fs = pa_frame_size(&u->sink_input->sample_spec);
    old_rate = u->sink_input->sample_spec.rate;
    base_rate = u->source_output->sample_spec.rate;

    if (u->latency_snapshot.min_memblockq_length < u->latency_snapshot.max_request*2)
        new_rate = base_rate - (((u->latency_snapshot.max_request*2 - u->latency_snapshot.min_memblockq_length) / fs) *PA_USEC_PER_SEC)/u->adjust_time;
    else
        new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time;

    if (new_rate < (uint32_t) (base_rate*0.8) || new_rate > (uint32_t) (base_rate*1.25)) {
        pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate, new_rate);
        new_rate = base_rate;
    } else {
        if (base_rate < new_rate + 20 && new_rate < base_rate + 20)
          new_rate = base_rate;
        /* Do the adjustment in small steps; 2‰ can be considered inaudible */
        if (new_rate < (uint32_t) (old_rate*0.998) || new_rate > (uint32_t) (old_rate*1.002)) {
            pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate, old_rate);
            new_rate = PA_CLAMP(new_rate, (uint32_t) (old_rate*0.998), (uint32_t) (old_rate*1.002));
        }
    }

    pa_sink_input_set_rate(u->sink_input, new_rate);
    pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);

    pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
}
static int parse_pos(const char *pos, double *f) {

    if (pa_atod(pos, f) < 0) {
        pa_log_warn("Failed to parse hpos/vpos property '%s'.", pos);
        return -1;
    }

    if (*f < 0.0 || *f > 1.0) {
        pa_log_debug("Property hpos/vpos out of range %0.2f", *f);

        *f = PA_CLAMP(*f, 0.0, 1.0);
    }

    return 0;
}
Пример #4
0
/* Called from thread context */
pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
    pa_source_output_assert_ref(o);
    pa_source_output_assert_io_context(o);

    if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
        usec = o->source->thread_info.fixed_latency;

    if (usec != (pa_usec_t) -1)
        usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency);

    o->thread_info.requested_source_latency = usec;
    pa_source_invalidate_requested_latency(o->source, TRUE);

    return usec;
}