AudioProfile.cpp revision 112b0af826aeca45855690b9c105b2cdf9938bbe
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "APM::AudioProfile" 18//#define LOG_NDEBUG 0 19 20#include "AudioProfile.h" 21#include "AudioPort.h" 22#include "HwModule.h" 23#include "AudioGain.h" 24#include <utils/SortedVector.h> 25#include "TypeConverter.h" 26#include <media/AudioResamplerPublic.h> 27#include <algorithm> 28 29namespace android { 30 31status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask, 32 audio_format_t format) const 33{ 34 if (format == mFormat && 35 (mChannelMasks.isEmpty() || supportsChannels(channelMask)) && 36 (mSamplingRates.isEmpty() || supportsRate(samplingRate))) { 37 return NO_ERROR; 38 } 39 return BAD_VALUE; 40} 41 42template <typename T> 43bool operator == (const SortedVector<T> &left, const SortedVector<T> &right) 44{ 45 if (left.size() != right.size()) { 46 return false; 47 } 48 for(size_t index = 0; index < right.size(); index++) { 49 if (left[index] != right[index]) { 50 return false; 51 } 52 } 53 return true; 54} 55 56bool operator == (const AudioProfile &left, const AudioProfile &compareTo) 57{ 58 return (left.getFormat() == compareTo.getFormat()) && 59 (left.getChannels() == compareTo.getChannels()) && 60 (left.getSampleRates() == compareTo.getSampleRates()); 61} 62 63status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate, 64 uint32_t &updatedSamplingRate) const 65{ 66 if (mSamplingRates.isEmpty()) { 67 updatedSamplingRate = samplingRate; 68 return NO_ERROR; 69 } 70 // Search for the closest supported sampling rate that is above (preferred) 71 // or below (acceptable) the desired sampling rate, within a permitted ratio. 72 // The sampling rates are sorted in ascending order. 73 size_t orderOfDesiredRate = mSamplingRates.orderOf(samplingRate); 74 75 // Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum. 76 if (orderOfDesiredRate < mSamplingRates.size()) { 77 uint32_t candidate = mSamplingRates[orderOfDesiredRate]; 78 if (candidate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) { 79 updatedSamplingRate = candidate; 80 return NO_ERROR; 81 } 82 } 83 // But if we have to up-sample from a lower sampling rate, that's OK. 84 if (orderOfDesiredRate != 0) { 85 uint32_t candidate = mSamplingRates[orderOfDesiredRate - 1]; 86 if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) { 87 updatedSamplingRate = candidate; 88 return NO_ERROR; 89 } 90 } 91 // leave updatedSamplingRate unmodified 92 return BAD_VALUE; 93} 94 95status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask, 96 audio_channel_mask_t &updatedChannelMask, 97 audio_port_type_t portType, 98 audio_port_role_t portRole) const 99{ 100 if (mChannelMasks.isEmpty()) { 101 updatedChannelMask = channelMask; 102 return NO_ERROR; 103 } 104 const bool isRecordThread = portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK; 105 const bool isIndex = audio_channel_mask_get_representation(channelMask) 106 == AUDIO_CHANNEL_REPRESENTATION_INDEX; 107 int bestMatch = 0; 108 for (size_t i = 0; i < mChannelMasks.size(); i ++) { 109 audio_channel_mask_t supported = mChannelMasks[i]; 110 if (supported == channelMask) { 111 // Exact matches always taken. 112 updatedChannelMask = channelMask; 113 return NO_ERROR; 114 } 115 116 // AUDIO_CHANNEL_NONE (value: 0) is used for dynamic channel support 117 if (isRecordThread && supported != AUDIO_CHANNEL_NONE) { 118 // Approximate (best) match: 119 // The match score measures how well the supported channel mask matches the 120 // desired mask, where increasing-is-better. 121 // 122 // TODO: Some tweaks may be needed. 123 // Should be a static function of the data processing library. 124 // 125 // In priority: 126 // match score = 1000 if legacy channel conversion equivalent (always prefer this) 127 // OR 128 // match score += 100 if the channel mask representations match 129 // match score += number of channels matched. 130 // 131 // If there are no matched channels, the mask may still be accepted 132 // but the playback or record will be silent. 133 const bool isSupportedIndex = (audio_channel_mask_get_representation(supported) 134 == AUDIO_CHANNEL_REPRESENTATION_INDEX); 135 int match; 136 if (isIndex && isSupportedIndex) { 137 // index equivalence 138 match = 100 + __builtin_popcount( 139 audio_channel_mask_get_bits(channelMask) 140 & audio_channel_mask_get_bits(supported)); 141 } else if (isIndex && !isSupportedIndex) { 142 const uint32_t equivalentBits = 143 (1 << audio_channel_count_from_in_mask(supported)) - 1 ; 144 match = __builtin_popcount( 145 audio_channel_mask_get_bits(channelMask) & equivalentBits); 146 } else if (!isIndex && isSupportedIndex) { 147 const uint32_t equivalentBits = 148 (1 << audio_channel_count_from_in_mask(channelMask)) - 1; 149 match = __builtin_popcount( 150 equivalentBits & audio_channel_mask_get_bits(supported)); 151 } else { 152 // positional equivalence 153 match = 100 + __builtin_popcount( 154 audio_channel_mask_get_bits(channelMask) 155 & audio_channel_mask_get_bits(supported)); 156 switch (supported) { 157 case AUDIO_CHANNEL_IN_FRONT_BACK: 158 case AUDIO_CHANNEL_IN_STEREO: 159 if (channelMask == AUDIO_CHANNEL_IN_MONO) { 160 match = 1000; 161 } 162 break; 163 case AUDIO_CHANNEL_IN_MONO: 164 if (channelMask == AUDIO_CHANNEL_IN_FRONT_BACK 165 || channelMask == AUDIO_CHANNEL_IN_STEREO) { 166 match = 1000; 167 } 168 break; 169 default: 170 break; 171 } 172 } 173 if (match > bestMatch) { 174 bestMatch = match; 175 updatedChannelMask = supported; 176 } 177 } 178 } 179 return bestMatch > 0 ? NO_ERROR : BAD_VALUE; 180} 181 182void AudioProfile::dump(int fd, int spaces) const 183{ 184 const size_t SIZE = 256; 185 char buffer[SIZE]; 186 String8 result; 187 188 snprintf(buffer, SIZE, "%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "", 189 mIsDynamicChannels ? "[dynamic channels]" : "", 190 mIsDynamicRate ? "[dynamic rates]" : ""); 191 result.append(buffer); 192 if (mName.length() != 0) { 193 snprintf(buffer, SIZE, "%*s- name: %s\n", spaces, "", mName.string()); 194 result.append(buffer); 195 } 196 std::string formatLiteral; 197 if (FormatConverter::toString(mFormat, formatLiteral)) { 198 snprintf(buffer, SIZE, "%*s- format: %s\n", spaces, "", formatLiteral.c_str()); 199 result.append(buffer); 200 } 201 if (!mSamplingRates.isEmpty()) { 202 snprintf(buffer, SIZE, "%*s- sampling rates:", spaces, ""); 203 result.append(buffer); 204 for (size_t i = 0; i < mSamplingRates.size(); i++) { 205 snprintf(buffer, SIZE, "%d", mSamplingRates[i]); 206 result.append(buffer); 207 result.append(i == (mSamplingRates.size() - 1) ? "" : ", "); 208 } 209 result.append("\n"); 210 } 211 212 if (!mChannelMasks.isEmpty()) { 213 snprintf(buffer, SIZE, "%*s- channel masks:", spaces, ""); 214 result.append(buffer); 215 for (size_t i = 0; i < mChannelMasks.size(); i++) { 216 snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); 217 result.append(buffer); 218 result.append(i == (mChannelMasks.size() - 1) ? "" : ", "); 219 } 220 result.append("\n"); 221 } 222 write(fd, result.string(), result.size()); 223} 224 225status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate, 226 audio_channel_mask_t channelMask, 227 audio_format_t format) const 228{ 229 if (isEmpty()) { 230 return NO_ERROR; 231 } 232 233 for (size_t i = 0; i < size(); i++) { 234 const sp<AudioProfile> profile = itemAt(i); 235 if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) { 236 return NO_ERROR; 237 } 238 } 239 return BAD_VALUE; 240} 241 242status_t AudioProfileVector::checkCompatibleProfile(uint32_t &samplingRate, 243 audio_channel_mask_t &channelMask, 244 audio_format_t &format, 245 audio_port_type_t portType, 246 audio_port_role_t portRole) const 247{ 248 if (isEmpty()) { 249 return NO_ERROR; 250 } 251 252 const bool checkInexact = // when port is input and format is linear pcm 253 portType == AUDIO_PORT_TYPE_MIX && portRole == AUDIO_PORT_ROLE_SINK 254 && audio_is_linear_pcm(format); 255 256 // iterate from best format to worst format (reverse order) 257 for (ssize_t i = size() - 1; i >= 0 ; --i) { 258 const sp<AudioProfile> profile = itemAt(i); 259 audio_format_t formatToCompare = profile->getFormat(); 260 if (formatToCompare == format || 261 (checkInexact 262 && formatToCompare != AUDIO_FORMAT_DEFAULT 263 && audio_is_linear_pcm(formatToCompare))) { 264 // Compatible profile has been found, checks if this profile has compatible 265 // rate and channels as well 266 audio_channel_mask_t updatedChannels; 267 uint32_t updatedRate; 268 if (profile->checkCompatibleChannelMask(channelMask, updatedChannels, 269 portType, portRole) == NO_ERROR && 270 profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) { 271 // for inexact checks we take the first linear pcm format due to sorting. 272 format = formatToCompare; 273 channelMask = updatedChannels; 274 samplingRate = updatedRate; 275 return NO_ERROR; 276 } 277 } 278 } 279 return BAD_VALUE; 280} 281 282int AudioProfileVector::compareFormats(const sp<AudioProfile> *profile1, 283 const sp<AudioProfile> *profile2) 284{ 285 return AudioPort::compareFormats((*profile1)->getFormat(), (*profile2)->getFormat()); 286} 287 288}; // namespace android 289