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 
     17 #include <stdint.h>
     18 #include <string.h>
     19 #include <tinyalsa/asoundlib.h>
     20 
     21 #include "audio/AudioHardware.h"
     22 #include "audio/Buffer.h"
     23 #include "Log.h"
     24 
     25 #include "audio/AudioRecordingLocal.h"
     26 
     27 
     28 AudioRecordingLocal::AudioRecordingLocal(int hwId)
     29     : mHwId(hwId),
     30       mPcmHandle(NULL)
     31 {
     32     LOGV("AudioRecordingLocal %x", (unsigned int)this);
     33 }
     34 
     35 AudioRecordingLocal::~AudioRecordingLocal()
     36 {
     37     LOGV("~AudioRecordingLocal %x", (unsigned int)this);
     38     releaseHw();
     39 }
     40 
     41 bool AudioRecordingLocal::doPrepare(AudioHardware::SamplingRate samplingRate, int samplesInOneGo)
     42 {
     43     releaseHw();
     44 
     45     struct pcm_config config;
     46 
     47     memset(&config, 0, sizeof(config));
     48     config.channels = 2;
     49     config.rate = samplingRate;
     50     config.period_size = 1024;
     51     config.period_count = 32;
     52     config.format = PCM_FORMAT_S16_LE;
     53     config.start_threshold = 0;
     54     config.stop_threshold = 0;
     55     config.silence_threshold = 0;
     56 
     57     mPcmHandle = pcm_open(mHwId, 0, PCM_IN, &config);
     58     if (!mPcmHandle || !pcm_is_ready(mPcmHandle)) {
     59        LOGE("Unable to open PCM device(%d) (%s)\n", mHwId, pcm_get_error(mPcmHandle));
     60        return false;
     61     }
     62 
     63     mSamples = samplesInOneGo;
     64     mSizes = samplesInOneGo * 4; // stereo, 16bit
     65 
     66     mBufferSize = pcm_get_buffer_size(mPcmHandle);
     67     LOGD("buffer size %d, read size %d", mBufferSize, mSizes);
     68     return true;
     69 }
     70 
     71 bool AudioRecordingLocal::doPlaybackOrRecord(android::sp<Buffer>& buffer)
     72 {
     73     int toRead = mSizes;
     74     if (buffer->amountToHandle() < (size_t)mSizes) {
     75         toRead = buffer->amountToHandle();
     76     }
     77     LOGD("recording will read %d", toRead);
     78 
     79     while (toRead > 0) {
     80         int readSize = (toRead > mBufferSize) ? mBufferSize : toRead;
     81         if (pcm_read(mPcmHandle, buffer->getUnhanledData(), readSize)) {
     82             LOGE("AudioRecordingLocal error %s", pcm_get_error(mPcmHandle));
     83             return false;
     84         }
     85         buffer->increaseHandled(readSize);
     86         toRead -= readSize;
     87     }
     88     LOGV("AudioRecordingLocal::doPlaybackOrRecord %d", buffer->amountHandled());
     89     return true;
     90 }
     91 
     92 void AudioRecordingLocal::doStop()
     93 {
     94     pcm_stop(mPcmHandle);
     95 }
     96 
     97 void AudioRecordingLocal::releaseHw()
     98 {
     99     if (mPcmHandle != NULL) {
    100         LOGV("releaseHw %x", (unsigned int)this);
    101         doStop();
    102         pcm_close(mPcmHandle);
    103         mPcmHandle = NULL;
    104     }
    105 }
    106