Android-x86
Fork

  • R/O
  • HTTP
  • SSH
  • HTTPS

hardware-libaudio: コミット

hardware/libaudio


コミットメタ情報

リビジョンfc4aceec5137d1658bedc97e257896e81bad625f (tree)
日時2020-04-23 23:49:22
作者Michael Goffioul <michael.goffioul@gmai...>
コミッターChih-Wei Huang

ログメッセージ

Support preprocessing filters in audio HAL

This adds support for some preprocessing filters like NS and AGC in the
audio HAL. This does not include AEC.

Derived from audio HAL in device/samsung/tuna and vero2-android-audio

変更サマリ

差分

--- a/audio_hw.c
+++ b/audio_hw.c
@@ -133,6 +133,7 @@ struct stream_out {
133133 struct audio_device *dev;
134134 };
135135
136+#define MAX_PREPROCESSORS 3
136137 struct stream_in {
137138 struct audio_stream_in stream;
138139
@@ -150,6 +151,12 @@ struct stream_in {
150151 int read_status;
151152
152153 struct audio_device *dev;
154+
155+ effect_handle_t preprocessors[MAX_PREPROCESSORS];
156+ int num_preprocessors;
157+ int16_t *proc_buf;
158+ size_t proc_buf_size;
159+ size_t proc_frames_in;
153160 };
154161
155162 enum {
@@ -332,6 +339,11 @@ static void do_in_standby(struct stream_in *in)
332339 free(in->buffer);
333340 in->buffer = NULL;
334341 }
342+ if (in->proc_buf) {
343+ free(in->proc_buf);
344+ in->proc_buf = NULL;
345+ in->proc_buf_size = 0;
346+ }
335347 in->standby = true;
336348 }
337349 }
@@ -577,6 +589,78 @@ static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
577589 return frames_wr;
578590 }
579591
592+static ssize_t process_frames(struct stream_in *in, void* buffer, ssize_t frames)
593+{
594+ ssize_t frames_wr = 0;
595+ audio_buffer_t in_buf;
596+ audio_buffer_t out_buf;
597+ int i;
598+
599+ while (frames_wr < frames) {
600+ /* first reload enough frames at the end of process input buffer */
601+ if (in->proc_frames_in < (size_t)frames) {
602+ ssize_t frames_rd;
603+
604+ if (in->proc_buf_size < (size_t)frames) {
605+ in->proc_buf_size = (size_t)frames;
606+ in->proc_buf = (int16_t *)realloc(in->proc_buf, in->proc_buf_size * sizeof(int16_t));
607+ ALOGV("process_frames(): in->proc_buf %p size extended to %zu frames",
608+ in->proc_buf, in->proc_buf_size);
609+ }
610+ frames_rd = read_frames(in,
611+ in->proc_buf + in->proc_frames_in,
612+ frames - in->proc_frames_in);
613+ if (frames_rd < 0) {
614+ frames_wr = frames_rd;
615+ break;
616+ }
617+
618+ in->proc_frames_in += frames_rd;
619+ }
620+
621+
622+ /* in_buf.frameCount and out_buf.frameCount indicate respectively
623+ * the maximum number of frames to be consumed and produced by process() */
624+ in_buf.frameCount = in->proc_frames_in;
625+ in_buf.s16 = in->proc_buf;
626+ out_buf.frameCount = frames - frames_wr;
627+ out_buf.s16 = (int16_t *)buffer + frames_wr;
628+
629+ /* FIXME: this works because of current pre processing library implementation that
630+ * does the actual process only when the last enabled effect process is called.
631+ * The generic solution is to have an output buffer for each effect and pass it as
632+ * input to the next. */
633+ for (i = 0; i < in->num_preprocessors; i++) {
634+ (*in->preprocessors[i])->process(in->preprocessors[i], &in_buf, &out_buf);
635+ }
636+
637+ /* process() has updated the number of frames consumed and produced in
638+ * in_buf.frameCount and out_buf.frameCount respectively
639+ * move remaining frames to the beginning of in->proc_buf_in */
640+ in->proc_frames_in -= in_buf.frameCount;
641+ if (in->proc_frames_in) {
642+ memmove(in->proc_buf,
643+ in->proc_buf + in_buf.frameCount,
644+ in->proc_frames_in * sizeof(int16_t));
645+ }
646+
647+ /* if not enough frames were passed to process(), read more and retry. */
648+ if (out_buf.frameCount == 0)
649+ continue;
650+
651+ if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
652+ frames_wr += out_buf.frameCount;
653+ } else {
654+ /* The effect does not comply to the API. In theory, we should never end up here! */
655+ ALOGE("preprocessing produced too many frames: %d + %zu > %d !",
656+ (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
657+ frames_wr = frames;
658+ }
659+ }
660+
661+ return frames_wr;
662+}
663+
580664 /* API functions */
581665
582666 static uint32_t out_get_sample_rate(const struct audio_stream *stream __unused)
@@ -1011,25 +1095,10 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
10111095 if (ret < 0)
10121096 goto exit;
10131097
1014- /*if (in->num_preprocessors != 0) {
1098+ if (in->num_preprocessors != 0) {
10151099 ret = process_frames(in, buffer, frames_rq);
1016- } else */if (in->resampler != NULL) {
1017- ret = read_frames(in, buffer, frames_rq);
1018- } else if (in->pcm_config->channels == 2) {
1019- /*
1020- * If the PCM is stereo, capture twice as many frames and
1021- * discard the right channel.
1022- */
1023- unsigned int i;
1024- int16_t *in_buffer = (int16_t *)buffer;
1025-
1026- ret = pcm_read(in->pcm, in->buffer, bytes * 2);
1027-
1028- /* Discard right channel */
1029- for (i = 0; i < frames_rq; i++)
1030- in_buffer[i] = in->buffer[i * 2];
10311100 } else {
1032- ret = pcm_read(in->pcm, buffer, bytes);
1101+ ret = read_frames(in, buffer, frames_rq);
10331102 }
10341103
10351104 if (ret > 0)
@@ -1056,16 +1125,63 @@ static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused
10561125 return 0;
10571126 }
10581127
1059-static int in_add_audio_effect(const struct audio_stream *stream __unused,
1060- effect_handle_t effect __unused)
1128+static int in_add_audio_effect(const struct audio_stream *stream,
1129+ effect_handle_t effect)
10611130 {
1062- return 0;
1131+ struct stream_in *in = (struct stream_in *)stream;
1132+ int status = 0;
1133+
1134+ pthread_mutex_lock(&in->dev->lock);
1135+ pthread_mutex_lock(&in->lock);
1136+ if (in->num_preprocessors >= MAX_PREPROCESSORS) {
1137+ status = -ENOSYS;
1138+ goto exit;
1139+ }
1140+
1141+ in->preprocessors[in->num_preprocessors++] = effect;
1142+
1143+exit:
1144+
1145+ pthread_mutex_unlock(&in->lock);
1146+ pthread_mutex_unlock(&in->dev->lock);
1147+ return status;
10631148 }
10641149
1065-static int in_remove_audio_effect(const struct audio_stream *stream __unused,
1066- effect_handle_t effect __unused)
1150+static int in_remove_audio_effect(const struct audio_stream *stream,
1151+ effect_handle_t effect)
10671152 {
1068- return 0;
1153+ struct stream_in *in = (struct stream_in *)stream;
1154+ int status = -EINVAL;
1155+ int i;
1156+
1157+ pthread_mutex_lock(&in->dev->lock);
1158+ pthread_mutex_lock(&in->lock);
1159+ if (in->num_preprocessors <= 0) {
1160+ status = -ENOSYS;
1161+ goto exit;
1162+ }
1163+
1164+ for (i = 0; i < in->num_preprocessors; i++) {
1165+ if (status == 0) {
1166+ in->preprocessors[i - 1] = in->preprocessors[i];
1167+ continue;
1168+ }
1169+ if (in->preprocessors[i] == effect) {
1170+ in->preprocessors[i] = NULL;
1171+ status = 0;
1172+ }
1173+ }
1174+
1175+ if (status != 0)
1176+ goto exit;
1177+
1178+ in->num_preprocessors--;
1179+
1180+exit:
1181+
1182+ pthread_mutex_unlock(&in->lock);
1183+ pthread_mutex_unlock(&in->dev->lock);
1184+ return status;
10691185 }
10701186
10711187
旧リポジトリブラウザで表示