1 /* 2 * Copyright (C) 2012 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 "NBAIO" 18 //#define LOG_NDEBUG 0 19 20 #include <utils/Log.h> 21 #include "NBAIO.h" 22 23 namespace android { 24 25 size_t Format_frameSize(NBAIO_Format format) 26 { 27 switch (format) { 28 case Format_SR44_1_C2_I16: 29 case Format_SR48_C2_I16: 30 return 2 * sizeof(short); 31 case Format_SR44_1_C1_I16: 32 case Format_SR48_C1_I16: 33 return 1 * sizeof(short); 34 case Format_Invalid: 35 default: 36 return 0; 37 } 38 } 39 40 size_t Format_frameBitShift(NBAIO_Format format) 41 { 42 switch (format) { 43 case Format_SR44_1_C2_I16: 44 case Format_SR48_C2_I16: 45 return 2; // 1 << 2 == 2 * sizeof(short) 46 case Format_SR44_1_C1_I16: 47 case Format_SR48_C1_I16: 48 return 1; // 1 << 1 == 1 * sizeof(short) 49 case Format_Invalid: 50 default: 51 return 0; 52 } 53 } 54 55 unsigned Format_sampleRate(NBAIO_Format format) 56 { 57 switch (format) { 58 case Format_SR44_1_C1_I16: 59 case Format_SR44_1_C2_I16: 60 return 44100; 61 case Format_SR48_C1_I16: 62 case Format_SR48_C2_I16: 63 return 48000; 64 case Format_Invalid: 65 default: 66 return 0; 67 } 68 } 69 70 unsigned Format_channelCount(NBAIO_Format format) 71 { 72 switch (format) { 73 case Format_SR44_1_C1_I16: 74 case Format_SR48_C1_I16: 75 return 1; 76 case Format_SR44_1_C2_I16: 77 case Format_SR48_C2_I16: 78 return 2; 79 case Format_Invalid: 80 default: 81 return 0; 82 } 83 } 84 85 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount) 86 { 87 if (sampleRate == 44100 && channelCount == 2) return Format_SR44_1_C2_I16; 88 if (sampleRate == 48000 && channelCount == 2) return Format_SR48_C2_I16; 89 if (sampleRate == 44100 && channelCount == 1) return Format_SR44_1_C1_I16; 90 if (sampleRate == 48000 && channelCount == 1) return Format_SR48_C1_I16; 91 return Format_Invalid; 92 } 93 94 // This is a default implementation; it is expected that subclasses will optimize this. 95 ssize_t NBAIO_Sink::writeVia(writeVia_t via, size_t total, void *user, size_t block) 96 { 97 if (!mNegotiated) { 98 return (ssize_t) NEGOTIATE; 99 } 100 static const size_t maxBlock = 32; 101 size_t frameSize = Format_frameSize(mFormat); 102 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 103 // double guarantees alignment for stack similar to what malloc() gives for heap 104 if (block == 0 || block > maxBlock) { 105 block = maxBlock; 106 } 107 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 108 size_t accumulator = 0; 109 while (accumulator < total) { 110 size_t count = total - accumulator; 111 if (count > block) { 112 count = block; 113 } 114 ssize_t ret = via(user, buffer, count); 115 if (ret > 0) { 116 ALOG_ASSERT((size_t) ret <= count); 117 size_t maxRet = ret; 118 ret = write(buffer, maxRet); 119 if (ret > 0) { 120 ALOG_ASSERT((size_t) ret <= maxRet); 121 accumulator += ret; 122 continue; 123 } 124 } 125 return accumulator > 0 ? accumulator : ret; 126 } 127 return accumulator; 128 } 129 130 // This is a default implementation; it is expected that subclasses will optimize this. 131 ssize_t NBAIO_Source::readVia(readVia_t via, size_t total, void *user, size_t block) 132 { 133 if (!mNegotiated) { 134 return (ssize_t) NEGOTIATE; 135 } 136 static const size_t maxBlock = 32; 137 size_t frameSize = Format_frameSize(mFormat); 138 ALOG_ASSERT(frameSize > 0 && frameSize <= 8); 139 // double guarantees alignment for stack similar to what malloc() gives for heap 140 if (block == 0 || block > maxBlock) { 141 block = maxBlock; 142 } 143 double buffer[((frameSize * block) + sizeof(double) - 1) / sizeof(double)]; 144 size_t accumulator = 0; 145 while (accumulator < total) { 146 size_t count = total - accumulator; 147 if (count > block) { 148 count = block; 149 } 150 ssize_t ret = read(buffer, count); 151 if (ret > 0) { 152 ALOG_ASSERT((size_t) ret <= count); 153 size_t maxRet = ret; 154 ret = via(user, buffer, maxRet); 155 if (ret > 0) { 156 ALOG_ASSERT((size_t) ret <= maxRet); 157 accumulator += ret; 158 continue; 159 } 160 } 161 return accumulator > 0 ? accumulator : ret; 162 } 163 return accumulator; 164 } 165 166 // Default implementation that only accepts my mFormat 167 ssize_t NBAIO_Port::negotiate(const NBAIO_Format offers[], size_t numOffers, 168 NBAIO_Format counterOffers[], size_t& numCounterOffers) 169 { 170 ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u", 171 offers, numOffers, counterOffers, numCounterOffers); 172 if (mFormat != Format_Invalid) { 173 for (size_t i = 0; i < numOffers; ++i) { 174 if (offers[i] == mFormat) { 175 mNegotiated = true; 176 return i; 177 } 178 } 179 if (numCounterOffers > 0) { 180 counterOffers[0] = mFormat; 181 } 182 numCounterOffers = 1; 183 } else { 184 numCounterOffers = 0; 185 } 186 return (ssize_t) NEGOTIATE; 187 } 188 189 } // namespace android 190