1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 #include <stdint.h>
17 #include <iostream>
18 #include <fstream>
19 #include <utils/String8.h>
20 #include "Log.h"
21 #include "StringUtil.h"
22 #include "audio/Buffer.h"
23 
Buffer(size_t capacity,size_t size,bool stereo)24 Buffer::Buffer(size_t capacity, size_t size, bool stereo)
25     : mCapacity(capacity),
26       mSize(size),
27       mHandled(0),
28       mStereo(stereo)
29 {
30     mData = new char[capacity];
31     //LOGV("Buffer %d data %x", capacity, (unsigned int)mData);
32     // assume 4bytes alignment
33     ASSERT(((long)mData & 0x3) == 0);
34     // filling with zero just to make valgrind happy.
35     // Otherwise, valgrind will complain about uninitialized data for all captured data
36     memset(mData, 0, capacity);
37 };
38 
~Buffer()39 Buffer::~Buffer()
40 {
41     delete[] mData;
42     //LOGV("~Buffer %d", mCapacity);
43 }
44 
changeToMono(ConvertOption option)45 void Buffer::changeToMono(ConvertOption option)
46 {
47     size_t newSize = mSize/2;
48     int16_t* data = reinterpret_cast<int16_t*>(mData);
49     if (option == EKeepCh0) {
50         for (size_t i = 0; i < newSize/2; i++) { //16bpp only
51             int16_t l = data[i * 2];
52             data[i] = l;
53         }
54     } else if (option == EKeepCh1) {
55         for (size_t i = 0; i < newSize/2; i++) { //16bpp only
56             int16_t r = data[i * 2 + 1];
57             data[i] = r;
58         }
59     } else { // average
60         for (size_t i = 0; i < newSize/2; i++) { //16bpp only
61             int16_t l = data[i * 2];
62             int16_t r = data[i * 2 + 1];
63             int16_t avr = (int16_t)(((int32_t)l + (int32_t)r)/2);
64             data[i] = avr;
65         }
66     }
67     mSize = newSize;
68     mHandled /= 2;
69     mStereo = false;
70 }
71 
changeToStereo()72 bool Buffer::changeToStereo()
73 {
74     //TODO ChangeToStereo
75     return false;
76 }
77 
78 const char* EXTENSION_S16_STEREO = ".r2s";
79 const char* EXTENSION_S16_MONO = ".r2m";
loadFromFile(const android::String8 & filename)80 Buffer* Buffer::loadFromFile(const android::String8& filename)
81 {
82     bool stereo;
83     if (StringUtil::endsWith(filename, EXTENSION_S16_STEREO)) {
84         stereo = true;
85     } else if (StringUtil::endsWith(filename, EXTENSION_S16_MONO)) {
86         stereo = false;
87     } else {
88         LOGE("Buffer::loadFromFile specified file %s has unknown extension.", filename.string());
89         return NULL;
90     }
91     std::ifstream file(filename.string(),  std::ios::in | std::ios::binary |
92             std::ios::ate);
93     if (!file.is_open()) {
94         LOGE("Buffer::loadFromFile cannot open file %s.", filename.string());
95         return NULL;
96     }
97     size_t size = file.tellg();
98     Buffer* buffer = new Buffer(size, size, stereo);
99     if (buffer == NULL) {
100         return NULL;
101     }
102     file.seekg(0, std::ios::beg);
103     file.read(buffer->mData, size); //TODO handle read error
104     file.close();
105     return buffer;
106 }
107 
saveToFile(const android::String8 & filename)108 bool Buffer::saveToFile(const android::String8& filename)
109 {
110     android::String8 filenameWithExtension(filename);
111     if (isStereo()) {
112         filenameWithExtension.append(EXTENSION_S16_STEREO);
113     } else {
114         filenameWithExtension.append(EXTENSION_S16_MONO);
115     }
116     std::ofstream file(filenameWithExtension.string(),  std::ios::out | std::ios::binary |
117             std::ios::trunc);
118     if (!file.is_open()) {
119         LOGE("Buffer::saveToFile cannot create file %s.",
120                 filenameWithExtension.string());
121         return false;
122     }
123     file.write(mData, mSize);
124     bool writeOK = true;
125     if (file.rdstate() != std::ios_base::goodbit) {
126         LOGE("Got error while writing file %s %x", filenameWithExtension.string(), file.rdstate());
127         writeOK = false;
128     }
129     file.close();
130     return writeOK;
131 }
132 
operator ==(const Buffer & b) const133 bool Buffer::operator == (const Buffer& b) const
134 {
135     if (mStereo != b.mStereo) {
136         LOGD("stereo mismatch %d %d", mStereo, b.mStereo);
137         return false;
138     }
139     if (mSize != b.mSize) {
140         LOGD("size mismatch %d %d", mSize, b.mSize);
141         return false;
142     }
143     for (size_t i = 0; i < mSize; i++) {
144         if (mData[i] != b.mData[i]) {
145             LOGD("%d %x vs %x", i, mData[i], b.mData[i]);
146             return false;
147         }
148     }
149     return true;
150 }
151