diff options
author | Chandrashekhar Urkeri | 2019-11-25 14:12:32 -0600 |
---|---|---|
committer | Praneeth Bajjuri | 2019-12-02 10:40:47 -0600 |
commit | b15dc329df62b17ba4c479b8523dac47000e9517 (patch) | |
tree | 51c65abdfb8e80542cf109ffdc597d64ef20bf58 | |
parent | fe55d7b090b2ca1c23ba449ad6b07337733a041a (diff) | |
download | hardware-ti-j721e-d-pie-core-release.tar.gz hardware-ti-j721e-d-pie-core-release.tar.xz hardware-ti-j721e-d-pie-core-release.zip |
j721e: audio: Implement the changes required for CDD compliance using 16 bit audio format.d-pie-core-release
As per Android's CDD doc (https://source.android.com/compatibility/9/android-9-cdd), the
audio HAL must support audio resampling between 8000, 11025, 16000, 44100 Hz using
Linear PCM, 16-bit format.But the Android's speex library cannot handle resampling of
24 bit audio format hence fall back to 16 bit audio format for both playback and
recording.
-rw-r--r-- | audio/primary/audio_hw.c | 379 | ||||
-rw-r--r-- | audio/primary/audio_policy_configuration.xml | 8 |
2 files changed, 376 insertions, 11 deletions
diff --git a/audio/primary/audio_hw.c b/audio/primary/audio_hw.c index 7787ad9..6c9b3cc 100644 --- a/audio/primary/audio_hw.c +++ b/audio/primary/audio_hw.c | |||
@@ -42,7 +42,18 @@ | |||
42 | /* yet another definition of ARRAY_SIZE macro) */ | 42 | /* yet another definition of ARRAY_SIZE macro) */ |
43 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) | 43 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) |
44 | 44 | ||
45 | #define DEFAULT_AUDIO_FORMAT AUDIO_FORMAT_PCM_24_BIT_PACKED | 45 | #define DEFAULT_AUDIO_FORMAT AUDIO_FORMAT_PCM_16_BIT |
46 | /* buffer_remix: functor for doing in-place buffer manipulations. | ||
47 | * | ||
48 | * NB. When remix_func is called, the memory at `buf` must be at least | ||
49 | * as large as frames * sample_size * MAX(in_chans, out_chans). | ||
50 | */ | ||
51 | struct buffer_remix { | ||
52 | void (*remix_func)(struct buffer_remix *data, void *buf, size_t frames); | ||
53 | size_t sample_size; /* size of one audio sample, in bytes */ | ||
54 | size_t in_chans; /* number of input channels */ | ||
55 | size_t out_chans; /* number of output channels */ | ||
56 | }; | ||
46 | 57 | ||
47 | struct j7_audio_device { | 58 | struct j7_audio_device { |
48 | struct audio_hw_device device; | 59 | struct audio_hw_device device; |
@@ -60,7 +71,10 @@ struct j7_stream_in { | |||
60 | struct j7_audio_device *dev; | 71 | struct j7_audio_device *dev; |
61 | struct pcm_config config; | 72 | struct pcm_config config; |
62 | struct pcm *pcm; | 73 | struct pcm *pcm; |
74 | struct buffer_remix *remix; /* adapt hw chan count to client */ | ||
75 | struct resampler_itfe *resampler; | ||
63 | struct resampler_buffer_provider buf_provider; | 76 | struct resampler_buffer_provider buf_provider; |
77 | int16_t *buffer; | ||
64 | size_t frames_in; | 78 | size_t frames_in; |
65 | size_t hw_frame_size; | 79 | size_t hw_frame_size; |
66 | unsigned int requested_rate; | 80 | unsigned int requested_rate; |
@@ -78,14 +92,17 @@ struct j7_stream_out { | |||
78 | struct j7_audio_device *dev; | 92 | struct j7_audio_device *dev; |
79 | struct pcm_config config; | 93 | struct pcm_config config; |
80 | struct pcm *pcm; | 94 | struct pcm *pcm; |
95 | struct resampler_itfe *resampler; | ||
81 | struct timespec last; | 96 | struct timespec last; |
82 | pthread_mutex_t lock; | 97 | pthread_mutex_t lock; |
98 | int16_t *buffer; | ||
83 | size_t hw_frame_size; | 99 | size_t hw_frame_size; |
84 | unsigned int requested_rate; | 100 | unsigned int requested_rate; |
85 | unsigned int requested_channels; | 101 | unsigned int requested_channels; |
86 | unsigned int card; | 102 | unsigned int card; |
87 | unsigned int port; | 103 | unsigned int port; |
88 | audio_devices_t device; | 104 | audio_devices_t device; |
105 | bool needs_remix; | ||
89 | bool standby; | 106 | bool standby; |
90 | int64_t written; /* total frames written, not cleared when entering standby */ | 107 | int64_t written; /* total frames written, not cleared when entering standby */ |
91 | }; | 108 | }; |
@@ -95,7 +112,7 @@ static const char *supported_media_cards[] = { | |||
95 | }; | 112 | }; |
96 | 113 | ||
97 | #define MAX_CARD_COUNT 1 | 114 | #define MAX_CARD_COUNT 1 |
98 | #define BYTES_PER_SAMPLE (3) //for 24 bit 3 bytes are required | 115 | #define BYTES_PER_SAMPLE (2) //for 16 bit 2 bytes are required |
99 | 116 | ||
100 | #define SUPPORTED_IN_DEVICES (AUDIO_DEVICE_IN_WIRED_HEADSET | \ | 117 | #define SUPPORTED_IN_DEVICES (AUDIO_DEVICE_IN_WIRED_HEADSET | \ |
101 | AUDIO_DEVICE_IN_DEFAULT) | 118 | AUDIO_DEVICE_IN_DEFAULT) |
@@ -118,7 +135,7 @@ static const char *supported_media_cards[] = { | |||
118 | struct pcm_config pcm_config_capture = { | 135 | struct pcm_config pcm_config_capture = { |
119 | .channels = 2,/* Stereo mode */ | 136 | .channels = 2,/* Stereo mode */ |
120 | .rate = CAPTURE_SAMPLE_RATE,/* 48K Hz*/ | 137 | .rate = CAPTURE_SAMPLE_RATE,/* 48K Hz*/ |
121 | .format = PCM_FORMAT_S24_3LE, | 138 | .format = PCM_FORMAT_S16_LE, |
122 | .period_size = CAPTURE_PERIOD_SIZE, | 139 | .period_size = CAPTURE_PERIOD_SIZE, |
123 | .period_count = CAPTURE_PERIOD_COUNT, | 140 | .period_count = CAPTURE_PERIOD_COUNT, |
124 | .start_threshold = 1, | 141 | .start_threshold = 1, |
@@ -128,7 +145,7 @@ struct pcm_config pcm_config_capture = { | |||
128 | struct pcm_config pcm_config_playback = { | 145 | struct pcm_config pcm_config_playback = { |
129 | .channels = 2,/* Stereo mode */ | 146 | .channels = 2,/* Stereo mode */ |
130 | .rate = PLAYBACK_SAMPLE_RATE,/* 48K Hz*/ | 147 | .rate = PLAYBACK_SAMPLE_RATE,/* 48K Hz*/ |
131 | .format = PCM_FORMAT_S24_3LE, | 148 | .format = PCM_FORMAT_S16_LE, |
132 | .period_size = PLAYBACK_PERIOD_SIZE, | 149 | .period_size = PLAYBACK_PERIOD_SIZE, |
133 | .period_count = PLAYBACK_PERIOD_COUNT, | 150 | .period_count = PLAYBACK_PERIOD_COUNT, |
134 | .start_threshold = PLAYBACK_BUFFER_SIZE / 2, | 151 | .start_threshold = PLAYBACK_BUFFER_SIZE / 2, |
@@ -179,6 +196,91 @@ static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channe | |||
179 | 196 | ||
180 | return size * channel_count * audio_bytes_per_sample(format); | 197 | return size * channel_count * audio_bytes_per_sample(format); |
181 | } | 198 | } |
199 | |||
200 | /* | ||
201 | * Implementation of buffer_remix::remix_func that removes | ||
202 | * channels in place without doing any other processing. The | ||
203 | * extra channels are truncated. | ||
204 | */ | ||
205 | static void remove_channels_from_buf(struct buffer_remix *data, void *buf, size_t frames) | ||
206 | { | ||
207 | size_t samp_size, in_frame, out_frame; | ||
208 | size_t N, c; | ||
209 | char *s, *d; | ||
210 | |||
211 | ALOGV("remove_channels_from_buf() remix=%p buf=%p frames=%zu", | ||
212 | data, buf, frames); | ||
213 | |||
214 | if (frames == 0) | ||
215 | return; | ||
216 | |||
217 | samp_size = data->sample_size; | ||
218 | in_frame = data->in_chans * samp_size; | ||
219 | out_frame = data->out_chans * samp_size; | ||
220 | |||
221 | if (out_frame >= in_frame) { | ||
222 | ALOGE("BUG: remove_channels_from_buf() can not add channels to a buffer.\n"); | ||
223 | return; | ||
224 | } | ||
225 | |||
226 | N = frames - 1; | ||
227 | d = (char*)buf + out_frame; | ||
228 | s = (char*)buf + in_frame; | ||
229 | |||
230 | /* take the first several channels and truncate the rest */ | ||
231 | while (N--) { | ||
232 | for (c = 0; c < out_frame; ++c) | ||
233 | d[c] = s[c]; | ||
234 | d += out_frame; | ||
235 | s += in_frame; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static int setup_stereo_to_mono_input_remix(struct j7_stream_in *in) | ||
240 | { | ||
241 | ALOGV("setup_stereo_to_mono_input_remix() stream=%p", in); | ||
242 | |||
243 | struct buffer_remix *br = (struct buffer_remix *)calloc(1, sizeof(struct buffer_remix)); | ||
244 | if (!br) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | br->remix_func = remove_channels_from_buf; | ||
248 | br->sample_size = BYTES_PER_SAMPLE; | ||
249 | br->in_chans = 2; | ||
250 | br->out_chans = 1; | ||
251 | in->remix = br; | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | |||
257 | static void mono_to_stereo(void *dst, const void *src, size_t frames, int sample_size) | ||
258 | { | ||
259 | int in_frame, out_frame; | ||
260 | int N, c; | ||
261 | char *s, *d; | ||
262 | |||
263 | ALOGV("mono_to_stereo() src=%p dst=%p frames=%zu", src, dst, frames); | ||
264 | |||
265 | if (frames == 0) | ||
266 | return; | ||
267 | |||
268 | in_frame = sample_size; | ||
269 | out_frame = 2 * sample_size; | ||
270 | |||
271 | N = frames - 1; | ||
272 | d = (char *)dst + N * out_frame; | ||
273 | s = (char *)src + N * in_frame; | ||
274 | |||
275 | /* duplicate first channel into the rest of channels in the frame */ | ||
276 | while (N-- >= 0) { | ||
277 | for (c = 0; c < out_frame; ++c) | ||
278 | d[c] = s[c % in_frame]; | ||
279 | d -= out_frame; | ||
280 | s -= in_frame; | ||
281 | } | ||
282 | } | ||
283 | |||
182 | /* audio HAL functions */ | 284 | /* audio HAL functions */ |
183 | 285 | ||
184 | static uint32_t out_get_sample_rate(const struct audio_stream *stream) | 286 | static uint32_t out_get_sample_rate(const struct audio_stream *stream) |
@@ -388,9 +490,23 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, | |||
388 | 490 | ||
389 | pthread_mutex_unlock(&adev->lock); | 491 | pthread_mutex_unlock(&adev->lock); |
390 | 492 | ||
391 | hw_frames = frames; | 493 | if (out->resampler) { |
392 | hw_buf = buffer; | 494 | in_buf = (void *)buffer; |
495 | hw_frames = out->config.period_size; | ||
496 | |||
497 | out->resampler->resample_from_input(out->resampler, | ||
498 | in_buf, &frames, | ||
499 | out->buffer, &hw_frames); | ||
500 | hw_buf = out->buffer; | ||
501 | } else { | ||
502 | hw_frames = frames; | ||
503 | hw_buf = buffer; | ||
504 | } | ||
393 | 505 | ||
506 | if (out->needs_remix) { | ||
507 | mono_to_stereo(out->buffer, hw_buf, hw_frames, BYTES_PER_SAMPLE); | ||
508 | hw_buf = out->buffer; | ||
509 | } | ||
394 | ret = pcm_write(out->pcm, hw_buf, hw_frames * out->hw_frame_size); | 510 | ret = pcm_write(out->pcm, hw_buf, hw_frames * out->hw_frame_size); |
395 | if (ret) { | 511 | if (ret) { |
396 | ALOGE("out_write() failed to write audio data %d", ret); | 512 | ALOGE("out_write() failed to write audio data %d", ret); |
@@ -617,6 +733,115 @@ static int in_set_gain(struct audio_stream_in *stream, float gain) | |||
617 | return 0; | 733 | return 0; |
618 | } | 734 | } |
619 | 735 | ||
736 | static int get_next_buffer(struct resampler_buffer_provider *buffer_provider, | ||
737 | struct resampler_buffer* buffer) | ||
738 | { | ||
739 | struct j7_stream_in *in; | ||
740 | struct buffer_remix *remix; | ||
741 | |||
742 | if (buffer_provider == NULL || buffer == NULL) | ||
743 | return -EINVAL; | ||
744 | |||
745 | in = (struct j7_stream_in *)((char *)buffer_provider - | ||
746 | offsetof(struct j7_stream_in, buf_provider)); | ||
747 | |||
748 | if (in->pcm == NULL) { | ||
749 | buffer->raw = NULL; | ||
750 | buffer->frame_count = 0; | ||
751 | in->read_status = -ENODEV; | ||
752 | return -ENODEV; | ||
753 | } | ||
754 | |||
755 | if (in->frames_in == 0) { | ||
756 | in->read_status = pcm_read(in->pcm, | ||
757 | (void*)in->buffer, | ||
758 | buffer->frame_count * in->hw_frame_size); | ||
759 | if (in->read_status != 0) { | ||
760 | ALOGE("get_next_buffer() pcm_read error %d", in->read_status); | ||
761 | buffer->raw = NULL; | ||
762 | buffer->frame_count = 0; | ||
763 | return in->read_status; | ||
764 | } | ||
765 | in->frames_in = buffer->frame_count; | ||
766 | |||
767 | remix = in->remix; | ||
768 | if (remix) | ||
769 | remix->remix_func(remix, in->buffer, in->frames_in); | ||
770 | } | ||
771 | |||
772 | buffer->frame_count = (buffer->frame_count > in->frames_in) ? | ||
773 | in->frames_in : buffer->frame_count; | ||
774 | buffer->i16 = in->buffer; | ||
775 | |||
776 | return in->read_status; | ||
777 | } | ||
778 | |||
779 | static void release_buffer(struct resampler_buffer_provider *buffer_provider, | ||
780 | struct resampler_buffer* buffer) | ||
781 | { | ||
782 | struct j7_stream_in *in; | ||
783 | |||
784 | if (buffer_provider == NULL || buffer == NULL) | ||
785 | return; | ||
786 | |||
787 | in = (struct j7_stream_in *)((char *)buffer_provider - | ||
788 | offsetof(struct j7_stream_in, buf_provider)); | ||
789 | |||
790 | in->frames_in -= buffer->frame_count; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * read_frames() reads frames from kernel driver, down samples to capture rate | ||
795 | * if necessary and output the number of frames requested to the buffer specified | ||
796 | */ | ||
797 | static ssize_t read_frames(struct j7_stream_in *in, void *buffer, ssize_t frames) | ||
798 | { | ||
799 | const struct audio_stream_in *s = (const struct audio_stream_in *)in; | ||
800 | ssize_t frames_wr = 0; | ||
801 | size_t frame_size; | ||
802 | |||
803 | ALOGV("read_frames() stream=%p frames=%zu", in, frames); | ||
804 | |||
805 | if (in->remix) | ||
806 | frame_size = audio_stream_in_frame_size(s); | ||
807 | else | ||
808 | frame_size = in->hw_frame_size; | ||
809 | |||
810 | while (frames_wr < frames) { | ||
811 | size_t frames_rd = frames - frames_wr; | ||
812 | |||
813 | if (in->resampler) { | ||
814 | in->resampler->resample_from_provider(in->resampler, | ||
815 | (int16_t *)((char *)buffer + frames_wr * frame_size), | ||
816 | &frames_rd); | ||
817 | } else { | ||
818 | struct resampler_buffer buf = { | ||
819 | { .raw = NULL, }, | ||
820 | .frame_count = frames_rd, | ||
821 | }; | ||
822 | |||
823 | get_next_buffer(&in->buf_provider, &buf); | ||
824 | if (buf.raw) { | ||
825 | memcpy((char *)buffer + frames_wr * frame_size, | ||
826 | buf.raw, | ||
827 | buf.frame_count * frame_size); | ||
828 | frames_rd = buf.frame_count; | ||
829 | } | ||
830 | release_buffer(&in->buf_provider, &buf); | ||
831 | } | ||
832 | |||
833 | /* in->read_status is updated by getNextBuffer() also called by | ||
834 | * in->resampler->resample_from_provider() */ | ||
835 | if (in->read_status != 0) | ||
836 | return in->read_status; | ||
837 | |||
838 | frames_wr += frames_rd; | ||
839 | |||
840 | } | ||
841 | |||
842 | return frames_wr; | ||
843 | } | ||
844 | |||
620 | static ssize_t in_read(struct audio_stream_in *stream, void* buffer, | 845 | static ssize_t in_read(struct audio_stream_in *stream, void* buffer, |
621 | size_t bytes) | 846 | size_t bytes) |
622 | { | 847 | { |
@@ -649,11 +874,22 @@ static ssize_t in_read(struct audio_stream_in *stream, void* buffer, | |||
649 | pthread_mutex_unlock(&adev->lock); | 874 | pthread_mutex_unlock(&adev->lock); |
650 | return -ENODEV; | 875 | return -ENODEV; |
651 | } | 876 | } |
877 | |||
878 | /* if no supported sample rate is available, use the resampler */ | ||
879 | if (in->resampler) { | ||
880 | in->resampler->reset(in->resampler); | ||
881 | in->frames_in = 0; | ||
882 | } | ||
883 | |||
652 | in->standby = false; | 884 | in->standby = false; |
653 | } | 885 | } |
654 | 886 | ||
655 | pthread_mutex_unlock(&adev->lock); | 887 | pthread_mutex_unlock(&adev->lock); |
656 | ret = pcm_read(in->pcm, buffer, bytes); | 888 | |
889 | if (in->resampler || in->remix) | ||
890 | ret = read_frames(in, buffer, frames); | ||
891 | else | ||
892 | ret = pcm_read(in->pcm, buffer, bytes); | ||
657 | 893 | ||
658 | if (ret < 0) { | 894 | if (ret < 0) { |
659 | ALOGE("in_read() failed to read audio data %d", ret); | 895 | ALOGE("in_read() failed to read audio data %d", ret); |
@@ -745,14 +981,70 @@ static int adev_open_output_stream(struct audio_hw_device *dev, | |||
745 | out->requested_rate = config->sample_rate; | 981 | out->requested_rate = config->sample_rate; |
746 | out->requested_channels = popcount(config->channel_mask); | 982 | out->requested_channels = popcount(config->channel_mask); |
747 | out->hw_frame_size = out->config.channels * BYTES_PER_SAMPLE; | 983 | out->hw_frame_size = out->config.channels * BYTES_PER_SAMPLE; |
984 | out->resampler = NULL; | ||
985 | out->buffer = NULL; | ||
748 | out->written = 0; | 986 | out->written = 0; |
749 | out->card = adev->card; | 987 | out->card = adev->card; |
750 | out->port = 0; | 988 | out->port = 0; |
751 | out->device = devices; | 989 | out->device = devices; |
752 | adev->out = out; | 990 | adev->out = out; |
991 | |||
992 | /* mono-to-stereo remix since playback stream is stereo */ | ||
993 | if (out->requested_channels == 1) { | ||
994 | ALOGV("adev_open_output_stream() mono-to-stereo remix needed"); | ||
995 | out->needs_remix = true; | ||
996 | } else if (out->requested_channels == 2) { | ||
997 | out->needs_remix = false; | ||
998 | } else { | ||
999 | ALOGE("adev_open_output_stream() %d channels is not supported", | ||
1000 | out->requested_channels); | ||
1001 | ret = -ENOTSUP; | ||
1002 | goto err1; | ||
1003 | } | ||
1004 | |||
1005 | if (out->requested_rate != out->config.rate) { | ||
1006 | ALOGV("adev_output_output_stream() resample needed, req=%uHz got=%uHz", | ||
1007 | out->requested_rate, out->config.rate); | ||
1008 | |||
1009 | ret = create_resampler(out->requested_rate, | ||
1010 | out->config.rate, | ||
1011 | out->requested_channels, | ||
1012 | RESAMPLER_QUALITY_DEFAULT, | ||
1013 | NULL, | ||
1014 | &out->resampler); | ||
1015 | if (ret) { | ||
1016 | ALOGE("adev_open_output_stream() failed to create resampler %d", ret); | ||
1017 | goto err1; | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | if (out->resampler || out->needs_remix) { | ||
1022 | /* | ||
1023 | * Supported sampling rates that require resampling are lower than the | ||
1024 | * HAL's default sampling rate (44.1kHz) so a buffer as large as the HAL's | ||
1025 | * will suffice | ||
1026 | */ | ||
1027 | buffer_size = out->config.period_size * out->hw_frame_size; | ||
1028 | |||
1029 | if (out->needs_remix) | ||
1030 | buffer_size *= 2; | ||
1031 | |||
1032 | out->buffer = malloc(buffer_size); | ||
1033 | if (!out->buffer) { | ||
1034 | ret = -ENOMEM; | ||
1035 | goto err2; | ||
1036 | } | ||
1037 | } | ||
1038 | |||
753 | *stream_out = &out->stream; | 1039 | *stream_out = &out->stream; |
754 | 1040 | ||
755 | return 0; | 1041 | return 0; |
1042 | |||
1043 | err2: | ||
1044 | release_resampler(out->resampler); | ||
1045 | err1: | ||
1046 | free(out); | ||
1047 | return ret; | ||
756 | } | 1048 | } |
757 | 1049 | ||
758 | static void adev_close_output_stream(struct audio_hw_device *dev, | 1050 | static void adev_close_output_stream(struct audio_hw_device *dev, |
@@ -765,6 +1057,12 @@ static void adev_close_output_stream(struct audio_hw_device *dev, | |||
765 | 1057 | ||
766 | out_standby(&stream->common); | 1058 | out_standby(&stream->common); |
767 | 1059 | ||
1060 | if (out->resampler) | ||
1061 | release_resampler(out->resampler); | ||
1062 | |||
1063 | if (out->buffer) | ||
1064 | free(out->buffer); | ||
1065 | |||
768 | free(out); | 1066 | free(out); |
769 | adev->out = NULL; | 1067 | adev->out = NULL; |
770 | } | 1068 | } |
@@ -941,13 +1239,71 @@ static int adev_open_input_stream(struct audio_hw_device *dev, | |||
941 | in->requested_rate = config->sample_rate; | 1239 | in->requested_rate = config->sample_rate; |
942 | in->requested_channels = popcount(config->channel_mask); | 1240 | in->requested_channels = popcount(config->channel_mask); |
943 | in->hw_frame_size = in->config.channels * BYTES_PER_SAMPLE; | 1241 | in->hw_frame_size = in->config.channels * BYTES_PER_SAMPLE; |
1242 | in->remix = NULL; | ||
1243 | in->resampler = NULL; | ||
1244 | in->buffer = NULL; | ||
944 | in->card = adev->card; | 1245 | in->card = adev->card; |
945 | in->port = 1; | 1246 | in->port = 1; |
946 | in->device = devices; | 1247 | in->device = devices; |
947 | adev->in = in; | 1248 | adev->in = in; |
1249 | |||
1250 | /* in-place stereo-to-mono remix since capture stream is stereo */ | ||
1251 | if (in->requested_channels == 1) { | ||
1252 | ALOGD("adev_open_input_stream() stereo-to-mono remix needed"); | ||
1253 | ret = setup_stereo_to_mono_input_remix(in); | ||
1254 | if (ret) { | ||
1255 | ALOGE("adev_open_input_stream() failed to setup remix %d", ret); | ||
1256 | goto err1; | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | if (in->requested_rate != in->config.rate) { | ||
1261 | ALOGD("adev_open_input_stream() resample needed, req=%uHz got=%uHz", | ||
1262 | in->requested_rate, in->config.rate); | ||
1263 | |||
1264 | in->buf_provider.get_next_buffer = get_next_buffer; | ||
1265 | in->buf_provider.release_buffer = release_buffer; | ||
1266 | ret = create_resampler(in->config.rate, | ||
1267 | in->requested_rate, | ||
1268 | in->requested_channels, | ||
1269 | RESAMPLER_QUALITY_DEFAULT, | ||
1270 | &in->buf_provider, | ||
1271 | &in->resampler); | ||
1272 | if (ret) { | ||
1273 | ALOGE("adev_open_input_stream() failed to create resampler %d", ret); | ||
1274 | goto err2; | ||
1275 | } | ||
1276 | } | ||
1277 | |||
1278 | /* | ||
1279 | * buffer size needs to be enough to allow stereo-to-mono remix | ||
1280 | * and resample if needed | ||
1281 | */ | ||
1282 | if (in->resampler || in->remix) { | ||
1283 | buffer_size = in->config.period_size * in->hw_frame_size; | ||
1284 | |||
1285 | if (in->resampler) | ||
1286 | buffer_size *= 2; | ||
1287 | if (in->remix) | ||
1288 | buffer_size *= 2; | ||
1289 | |||
1290 | in->buffer = malloc(buffer_size); | ||
1291 | if (!in->buffer) { | ||
1292 | ret = -ENOMEM; | ||
1293 | goto err3; | ||
1294 | } | ||
1295 | } | ||
948 | *stream_in = &in->stream; | 1296 | *stream_in = &in->stream; |
949 | 1297 | ||
950 | return 0; | 1298 | return 0; |
1299 | |||
1300 | err3: | ||
1301 | release_resampler(in->resampler); | ||
1302 | err2: | ||
1303 | free(in->remix); | ||
1304 | err1: | ||
1305 | free(in); | ||
1306 | return ret; | ||
951 | } | 1307 | } |
952 | 1308 | ||
953 | static void adev_close_input_stream(struct audio_hw_device *dev, | 1309 | static void adev_close_input_stream(struct audio_hw_device *dev, |
@@ -960,6 +1316,15 @@ static void adev_close_input_stream(struct audio_hw_device *dev, | |||
960 | 1316 | ||
961 | in_standby(&stream->common); | 1317 | in_standby(&stream->common); |
962 | 1318 | ||
1319 | if (in->resampler) | ||
1320 | release_resampler(in->resampler); | ||
1321 | |||
1322 | if (in->remix) | ||
1323 | free(in->remix); | ||
1324 | |||
1325 | if (in->buffer) | ||
1326 | free(in->buffer); | ||
1327 | |||
963 | free(in); | 1328 | free(in); |
964 | adev->in = NULL; | 1329 | adev->in = NULL; |
965 | } | 1330 | } |
diff --git a/audio/primary/audio_policy_configuration.xml b/audio/primary/audio_policy_configuration.xml index a4fc066..3cd301e 100644 --- a/audio/primary/audio_policy_configuration.xml +++ b/audio/primary/audio_policy_configuration.xml | |||
@@ -10,13 +10,13 @@ | |||
10 | 10 | ||
11 | <mixPorts> | 11 | <mixPorts> |
12 | <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> | 12 | <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY"> |
13 | <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED" | 13 | <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" |
14 | samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> | 14 | samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> |
15 | </mixPort> | 15 | </mixPort> |
16 | <mixPort name="primary input" role="sink"> | 16 | <mixPort name="primary input" role="sink"> |
17 | <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED" | 17 | <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" |
18 | samplingRates="48000" | 18 | samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000" |
19 | channelMasks="AUDIO_CHANNEL_IN_STEREO"/> | 19 | channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/> |
20 | </mixPort> | 20 | </mixPort> |
21 | </mixPorts> | 21 | </mixPorts> |
22 | 22 | ||