From 8dc1031453377d2f9d9c7847027f276e6726a4c8 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Thu, 20 Nov 2014 12:41:26 -0800 Subject: [PATCH] Convert record channel mask for dynamic mix When creating the AudioRecord instance for a dynamic mix, convert the output channel mask of the mix to an input channel mask to be used by the AudioRecord instance through which the mixed audio is rerouted. Bug 16009464 Change-Id: I3addbe85339f6f06b69acc3f9b8e2a765e5d7305 --- media/java/android/media/AudioFormat.java | 23 +++++++++++++++++++ .../media/audiopolicy/AudioPolicy.java | 9 +++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index 58ed4f808779a..9a0266d8bd9d7 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -126,6 +126,29 @@ public class AudioFormat { CHANNEL_OUT_LOW_FREQUENCY); // CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL + /** + * @hide + * Return the input channel mask corresponding to an output channel mask. + * This can be used for submix rerouting for the mask of the recorder to map to that of the mix. + * @param outMask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT + * @return a combination of CHANNEL_IN_* definitions matching an output channel mask + * @throws IllegalArgumentException + */ + public static int inChannelMaskFromOutChannelMask(int outMask) throws IllegalArgumentException { + if (outMask == CHANNEL_OUT_DEFAULT) { + throw new IllegalArgumentException( + "Illegal CHANNEL_OUT_DEFAULT channel mask for input."); + } + switch (channelCountFromOutChannelMask(outMask)) { + case 1: + return CHANNEL_IN_MONO; + case 2: + return CHANNEL_IN_STEREO; + default: + throw new IllegalArgumentException("Unsupported channel configuration for input."); + } + } + /** * @hide * Return the number of channels from an input channel mask diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java index 255d828b4bfab..e9dc3af568828 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -155,6 +155,7 @@ public class AudioPolicy { { throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back"); } + // TODO also check mix is defined for playback or recording, and matches forTrack argument } /** @@ -175,13 +176,19 @@ public class AudioPolicy { return null; } checkMixReadyToUse(mix, false/*not for an AudioTrack*/); + // create an AudioFormat from the mix format compatible with recording, as the mix + // was defined for playback + AudioFormat mixFormat = new AudioFormat.Builder(mix.getFormat()) + .setChannelMask(AudioFormat.inChannelMaskFromOutChannelMask( + mix.getFormat().getChannelMask())) + .build(); // create the AudioRecord, configured for loop back, using the same format as the mix AudioRecord ar = new AudioRecord( new AudioAttributes.Builder() .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX) .addTag(mix.getRegistration()) .build(), - mix.getFormat(), + mixFormat, AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(), // using stereo for buffer size to avoid the current poor support for masks AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),