Merge "Improve stub hal read and write timing" into nyc-mr1-dev
This commit is contained in:
@@ -35,10 +35,12 @@ struct stub_audio_device {
|
||||
|
||||
struct stub_stream_out {
|
||||
struct audio_stream_out stream;
|
||||
int64_t last_write_time_us;
|
||||
};
|
||||
|
||||
struct stub_stream_in {
|
||||
struct audio_stream_in stream;
|
||||
int64_t last_read_time_us;
|
||||
};
|
||||
|
||||
static uint32_t out_get_sample_rate(const struct audio_stream *stream)
|
||||
@@ -79,7 +81,7 @@ static int out_set_format(struct audio_stream *stream, audio_format_t format)
|
||||
static int out_standby(struct audio_stream *stream)
|
||||
{
|
||||
ALOGV("out_standby");
|
||||
|
||||
// out->last_write_time_us = 0; unnecessary as a stale write time has same effect
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -118,9 +120,31 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
|
||||
size_t bytes)
|
||||
{
|
||||
ALOGV("out_write: bytes: %d", bytes);
|
||||
|
||||
/* XXX: fake timing for audio output */
|
||||
usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
|
||||
out_get_sample_rate(&stream->common));
|
||||
struct stub_stream_out *out = (struct stub_stream_out *)stream;
|
||||
struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
|
||||
const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
|
||||
int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
|
||||
out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
|
||||
if (sleep_time > 0) {
|
||||
usleep(sleep_time);
|
||||
} else {
|
||||
// we don't sleep when we exit standby (this is typical for a real alsa buffer).
|
||||
sleep_time = 0;
|
||||
}
|
||||
out->last_write_time_us = now + sleep_time;
|
||||
// last_write_time_us is an approximation of when the (simulated) alsa
|
||||
// buffer is believed completely full. The usleep above waits for more space
|
||||
// in the buffer, but by the end of the sleep the buffer is considered
|
||||
// topped-off.
|
||||
//
|
||||
// On the subsequent out_write(), we measure the elapsed time spent in
|
||||
// the mixer. This is subtracted from the sleep estimate based on frames,
|
||||
// thereby accounting for drain in the alsa buffer during mixing.
|
||||
// This is a crude approximation; we don't handle underruns precisely.
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@@ -189,6 +213,8 @@ static int in_set_format(struct audio_stream *stream, audio_format_t format)
|
||||
|
||||
static int in_standby(struct audio_stream *stream)
|
||||
{
|
||||
struct stub_stream_in *in = (struct stub_stream_in *)stream;
|
||||
in->last_read_time_us = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -217,9 +243,31 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
|
||||
size_t bytes)
|
||||
{
|
||||
ALOGV("in_read: bytes %d", bytes);
|
||||
|
||||
/* XXX: fake timing for audio input */
|
||||
usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
|
||||
in_get_sample_rate(&stream->common));
|
||||
struct stub_stream_in *in = (struct stub_stream_in *)stream;
|
||||
struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
|
||||
|
||||
// we do a full sleep when exiting standby.
|
||||
const bool standby = in->last_read_time_us == 0;
|
||||
const int64_t elapsed_time_since_last_read = standby ?
|
||||
0 : now - in->last_read_time_us;
|
||||
int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
|
||||
in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
|
||||
if (sleep_time > 0) {
|
||||
usleep(sleep_time);
|
||||
} else {
|
||||
sleep_time = 0;
|
||||
}
|
||||
in->last_read_time_us = now + sleep_time;
|
||||
// last_read_time_us is an approximation of when the (simulated) alsa
|
||||
// buffer is drained by the read, and is empty.
|
||||
//
|
||||
// On the subsequent in_read(), we measure the elapsed time spent in
|
||||
// the recording thread. This is subtracted from the sleep estimate based on frames,
|
||||
// thereby accounting for fill in the alsa buffer during the interim.
|
||||
memset(buffer, 0, bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user