Home | History | Annotate | Download | only in audioflinger
      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