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