Home | History | Annotate | Download | only in audio
      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 
     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 
     39 Buffer::~Buffer()
     40 {
     41     delete[] mData;
     42     //LOGV("~Buffer %d", mCapacity);
     43 }
     44 
     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 
     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";
     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 
    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 
    133 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