• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Format_frameSize(NBAIO_Format format)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 
Format_frameBitShift(NBAIO_Format format)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 
Format_sampleRate(NBAIO_Format format)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 
Format_channelCount(NBAIO_Format format)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 
Format_from_SR_C(unsigned sampleRate,unsigned channelCount)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.
writeVia(writeVia_t via,size_t total,void * user,size_t block)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.
readVia(readVia_t via,size_t total,void * user,size_t block)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
negotiate(const NBAIO_Format offers[],size_t numOffers,NBAIO_Format counterOffers[],size_t & numCounterOffers)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