summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChih-Wei Huang <cwhuang@linux.org.tw>2020-04-23 22:59:10 +0800
committerChih-Wei Huang <cwhuang@linux.org.tw>2020-04-23 22:59:10 +0800
commit5649870a49cac156bc37f1b164b5e17e84e1c28c (patch)
tree2f9a2c440832718e7f957ad959f0156144b70b37
parent7a7fa62195e51b151a52de1ea9d24800883680f9 (diff)
parentfc4aceec5137d1658bedc97e257896e81bad625f (diff)
downloadplatform_hardware_libaudio-q-x86.tar.gz
platform_hardware_libaudio-q-x86.tar.bz2
platform_hardware_libaudio-q-x86.zip
Merge remote-tracking branch 'x86/pie-x86' into q-x86q-x86
-rw-r--r--audio_hw.c162
1 files changed, 139 insertions, 23 deletions
diff --git a/audio_hw.c b/audio_hw.c
index aa83b9e..1b24995 100644
--- a/audio_hw.c
+++ b/audio_hw.c
@@ -132,6 +132,7 @@ struct stream_out {
struct audio_device *dev;
};
+#define MAX_PREPROCESSORS 3
struct stream_in {
struct audio_stream_in stream;
@@ -149,6 +150,12 @@ struct stream_in {
int read_status;
struct audio_device *dev;
+
+ effect_handle_t preprocessors[MAX_PREPROCESSORS];
+ int num_preprocessors;
+ int16_t *proc_buf;
+ size_t proc_buf_size;
+ size_t proc_frames_in;
};
static uint32_t out_get_sample_rate(const struct audio_stream *stream);
@@ -320,6 +327,11 @@ static void do_in_standby(struct stream_in *in)
free(in->buffer);
in->buffer = NULL;
}
+ if (in->proc_buf) {
+ free(in->proc_buf);
+ in->proc_buf = NULL;
+ in->proc_buf_size = 0;
+ }
in->standby = true;
}
}
@@ -565,6 +577,78 @@ static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
return frames_wr;
}
+static ssize_t process_frames(struct stream_in *in, void* buffer, ssize_t frames)
+{
+ ssize_t frames_wr = 0;
+ audio_buffer_t in_buf;
+ audio_buffer_t out_buf;
+ int i;
+
+ while (frames_wr < frames) {
+ /* first reload enough frames at the end of process input buffer */
+ if (in->proc_frames_in < (size_t)frames) {
+ ssize_t frames_rd;
+
+ if (in->proc_buf_size < (size_t)frames) {
+ in->proc_buf_size = (size_t)frames;
+ in->proc_buf = (int16_t *)realloc(in->proc_buf, in->proc_buf_size * sizeof(int16_t));
+ ALOGV("process_frames(): in->proc_buf %p size extended to %zu frames",
+ in->proc_buf, in->proc_buf_size);
+ }
+ frames_rd = read_frames(in,
+ in->proc_buf + in->proc_frames_in,
+ frames - in->proc_frames_in);
+ if (frames_rd < 0) {
+ frames_wr = frames_rd;
+ break;
+ }
+
+ in->proc_frames_in += frames_rd;
+ }
+
+
+ /* in_buf.frameCount and out_buf.frameCount indicate respectively
+ * the maximum number of frames to be consumed and produced by process() */
+ in_buf.frameCount = in->proc_frames_in;
+ in_buf.s16 = in->proc_buf;
+ out_buf.frameCount = frames - frames_wr;
+ out_buf.s16 = (int16_t *)buffer + frames_wr;
+
+ /* FIXME: this works because of current pre processing library implementation that
+ * does the actual process only when the last enabled effect process is called.
+ * The generic solution is to have an output buffer for each effect and pass it as
+ * input to the next. */
+ for (i = 0; i < in->num_preprocessors; i++) {
+ (*in->preprocessors[i])->process(in->preprocessors[i], &in_buf, &out_buf);
+ }
+
+ /* process() has updated the number of frames consumed and produced in
+ * in_buf.frameCount and out_buf.frameCount respectively
+ * move remaining frames to the beginning of in->proc_buf_in */
+ in->proc_frames_in -= in_buf.frameCount;
+ if (in->proc_frames_in) {
+ memmove(in->proc_buf,
+ in->proc_buf + in_buf.frameCount,
+ in->proc_frames_in * sizeof(int16_t));
+ }
+
+ /* if not enough frames were passed to process(), read more and retry. */
+ if (out_buf.frameCount == 0)
+ continue;
+
+ if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
+ frames_wr += out_buf.frameCount;
+ } else {
+ /* The effect does not comply to the API. In theory, we should never end up here! */
+ ALOGE("preprocessing produced too many frames: %d + %zu > %d !",
+ (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
+ frames_wr = frames;
+ }
+ }
+
+ return frames_wr;
+}
+
/* API functions */
static uint32_t out_get_sample_rate(const struct audio_stream *stream __unused)
@@ -999,25 +1083,10 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
if (ret < 0)
goto exit;
- /*if (in->num_preprocessors != 0) {
+ if (in->num_preprocessors != 0) {
ret = process_frames(in, buffer, frames_rq);
- } else */if (in->resampler != NULL) {
- ret = read_frames(in, buffer, frames_rq);
- } else if (in->pcm_config->channels == 2) {
- /*
- * If the PCM is stereo, capture twice as many frames and
- * discard the right channel.
- */
- unsigned int i;
- int16_t *in_buffer = (int16_t *)buffer;
-
- ret = pcm_read(in->pcm, in->buffer, bytes * 2);
-
- /* Discard right channel */
- for (i = 0; i < frames_rq; i++)
- in_buffer[i] = in->buffer[i * 2];
} else {
- ret = pcm_read(in->pcm, buffer, bytes);
+ ret = read_frames(in, buffer, frames_rq);
}
if (ret > 0)
@@ -1044,16 +1113,63 @@ static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused
return 0;
}
-static int in_add_audio_effect(const struct audio_stream *stream __unused,
- effect_handle_t effect __unused)
+static int in_add_audio_effect(const struct audio_stream *stream,
+ effect_handle_t effect)
{
- return 0;
+ struct stream_in *in = (struct stream_in *)stream;
+ int status = 0;
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+ if (in->num_preprocessors >= MAX_PREPROCESSORS) {
+ status = -ENOSYS;
+ goto exit;
+ }
+
+ in->preprocessors[in->num_preprocessors++] = effect;
+
+exit:
+
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
+ return status;
}
-static int in_remove_audio_effect(const struct audio_stream *stream __unused,
- effect_handle_t effect __unused)
+static int in_remove_audio_effect(const struct audio_stream *stream,
+ effect_handle_t effect)
{
- return 0;
+ struct stream_in *in = (struct stream_in *)stream;
+ int status = -EINVAL;
+ int i;
+
+ pthread_mutex_lock(&in->dev->lock);
+ pthread_mutex_lock(&in->lock);
+ if (in->num_preprocessors <= 0) {
+ status = -ENOSYS;
+ goto exit;
+ }
+
+ for (i = 0; i < in->num_preprocessors; i++) {
+ if (status == 0) {
+ in->preprocessors[i - 1] = in->preprocessors[i];
+ continue;
+ }
+ if (in->preprocessors[i] == effect) {
+ in->preprocessors[i] = NULL;
+ status = 0;
+ }
+ }
+
+ if (status != 0)
+ goto exit;
+
+ in->num_preprocessors--;
+
+exit:
+
+ pthread_mutex_unlock(&in->lock);
+ pthread_mutex_unlock(&in->dev->lock);
+ return status;
}