blob: 321984c4b61c4e95d94248c5d9d3f6d3ddbecacc [file] [log] [blame]
Iliyan Malchev4765c432012-06-11 14:36:16 -07001/* AudioStreamInALSA.cpp
2 **
3 ** Copyright 2008-2009 Wind River Systems
4 ** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
5 **
6 ** Licensed under the Apache License, Version 2.0 (the "License");
7 ** you may not use this file except in compliance with the License.
8 ** You may obtain a copy of the License at
9 **
10 ** http://www.apache.org/licenses/LICENSE-2.0
11 **
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 */
18
19#include <errno.h>
20#include <stdarg.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <dlfcn.h>
26
27#define LOG_TAG "AudioStreamInALSA"
28//#define LOG_NDEBUG 0
29#define LOG_NDDEBUG 0
30#include <utils/Log.h>
31#include <utils/String8.h>
32
33#include <cutils/properties.h>
34#include <media/AudioRecord.h>
35#include <hardware_legacy/power.h>
36
37#include "AudioHardwareALSA.h"
38
39extern "C" {
40#if 0
41#include "csd_client.h"
42#endif
43#ifdef SSR_ENABLED
44#include "surround_filters_interface.h"
45#endif
46}
47
48namespace android_audio_legacy
49{
50#ifdef SSR_ENABLED
51#define SURROUND_FILE_1R "/system/etc/surround_sound/filter1r.pcm"
52#define SURROUND_FILE_2R "/system/etc/surround_sound/filter2r.pcm"
53#define SURROUND_FILE_3R "/system/etc/surround_sound/filter3r.pcm"
54#define SURROUND_FILE_4R "/system/etc/surround_sound/filter4r.pcm"
55
56#define SURROUND_FILE_1I "/system/etc/surround_sound/filter1i.pcm"
57#define SURROUND_FILE_2I "/system/etc/surround_sound/filter2i.pcm"
58#define SURROUND_FILE_3I "/system/etc/surround_sound/filter3i.pcm"
59#define SURROUND_FILE_4I "/system/etc/surround_sound/filter4i.pcm"
60
61// Use AAC/DTS channel mapping as default channel mapping: C,FL,FR,Ls,Rs,LFE
62const int chanMap[] = { 1, 2, 4, 3, 0, 5 };
63#endif
64
65AudioStreamInALSA::AudioStreamInALSA(AudioHardwareALSA *parent,
66 alsa_handle_t *handle,
67 AudioSystem::audio_in_acoustics audio_acoustics) :
68 ALSAStreamOps(parent, handle),
69 mFramesLost(0),
70 mParent(parent),
71 mAcoustics(audio_acoustics)
72#ifdef SSR_ENABLED
73 , mFp_4ch(NULL),
74 mFp_6ch(NULL),
75 mRealCoeffs(NULL),
76 mImagCoeffs(NULL),
77 mSurroundObj(NULL),
78 mSurroundOutputBuffer(NULL),
79 mSurroundInputBuffer(NULL),
80 mSurroundOutputBufferIdx(0),
81 mSurroundInputBufferIdx(0)
82#endif
83{
84#ifdef SSR_ENABLED
85 char c_multi_ch_dump[128] = {0};
86 status_t err = NO_ERROR;
87
88 // Call surround sound library init if device is Surround Sound
89 if ( handle->channels == 6) {
90 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
91 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
92
93 err = initSurroundSoundLibrary(handle->bufferSize);
94 if ( NO_ERROR != err) {
95 LOGE("initSurroundSoundLibrary failed: %d handle->bufferSize:%d", err,handle->bufferSize);
96 }
97
98 property_get("ssr.pcmdump",c_multi_ch_dump,"0");
99 if (0 == strncmp("true",c_multi_ch_dump, sizeof("ssr.dump-pcm"))) {
100 //Remember to change file system permission of data(e.g. chmod 777 data/),
101 //otherwise, fopen may fail.
102 if ( !mFp_4ch)
103 mFp_4ch = fopen("/data/4ch_ssr.pcm", "wb");
104 if ( !mFp_6ch)
105 mFp_6ch = fopen("/data/6ch_ssr.pcm", "wb");
106 if ((!mFp_4ch) || (!mFp_6ch))
107 LOGE("mfp_4ch or mfp_6ch open failed: mfp_4ch:%p mfp_6ch:%p",mFp_4ch,mFp_6ch);
108 }
109 }
110 }
111#endif
112}
113
114AudioStreamInALSA::~AudioStreamInALSA()
115{
116 close();
117}
118
119status_t AudioStreamInALSA::setGain(float gain)
120{
121 return 0; //mixer() ? mixer()->setMasterGain(gain) : (status_t)NO_INIT;
122}
123
124ssize_t AudioStreamInALSA::read(void *buffer, ssize_t bytes)
125{
126 int period_size;
127
128 LOGV("read:: buffer %p, bytes %d", buffer, bytes);
129
130 int n;
131 status_t err;
132 size_t read = 0;
133 char *use_case;
134 int newMode = mParent->mode();
135
136 if((mHandle->handle == NULL) && (mHandle->rxHandle == NULL) &&
137 (strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) &&
138 (strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
139 mParent->mLock.lock();
140 snd_use_case_get(mHandle->ucMgr, "_verb", (const char **)&use_case);
141 if ((use_case != NULL) && (strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
142 if ((mHandle->devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
143 (newMode == AudioSystem::MODE_IN_CALL)) {
144 LOGD("read:: mParent->mIncallMode=%d", mParent->mIncallMode);
145 if ((mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
146 (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
147#if 0
148 if (mParent->mFusion3Platform) {
149 mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
150 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
151 sizeof(mHandle->useCase));
152 csd_client_start_record(INCALL_REC_STEREO);
153 } else
154#endif
155 {
156 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
157 sizeof(mHandle->useCase));
158 }
159 } else if (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
160#if 0
161 if (mParent->mFusion3Platform) {
162 mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
163 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
164 sizeof(mHandle->useCase));
165 csd_client_start_record(INCALL_REC_MONO);
166 } else
167#endif
168 {
169 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
170 sizeof(mHandle->useCase));
171 }
172 }
173#if 0
174 } else if(mHandle->devices == AudioSystem::DEVICE_IN_FM_RX) {
175 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_FM, sizeof(mHandle->useCase));
176 } else if (mHandle->devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
177 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(mHandle->useCase));
178#endif
179 } else if(!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) {
180 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, sizeof(mHandle->useCase));
181 }else {
182 strlcpy(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(mHandle->useCase));
183 }
184 } else {
185 if ((mHandle->devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
186 (newMode == AudioSystem::MODE_IN_CALL)) {
187 LOGD("read:: ---- mParent->mIncallMode=%d", mParent->mIncallMode);
188 if ((mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_UPLINK) &&
189 (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK)) {
190#if 0
191 if (mParent->mFusion3Platform) {
192 mParent->mALSADevice->setVocRecMode(INCALL_REC_STEREO);
193 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
194 sizeof(mHandle->useCase));
195 csd_client_start_record(INCALL_REC_STEREO);
196 } else
197#endif
198 {
199 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_UL_DL_REC,
200 sizeof(mHandle->useCase));
201 }
202 } else if (mParent->mIncallMode & AudioSystem::CHANNEL_IN_VOICE_DNLINK) {
203#if 0
204 if (mParent->mFusion3Platform) {
205 mParent->mALSADevice->setVocRecMode(INCALL_REC_MONO);
206 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC,
207 sizeof(mHandle->useCase));
208 csd_client_start_record(INCALL_REC_MONO);
209 } else
210#endif
211 {
212 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_DL_REC,
213 sizeof(mHandle->useCase));
214 }
215 }
216#if 0
217 } else if(mHandle->devices == AudioSystem::DEVICE_IN_FM_RX) {
218 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_FM_REC, sizeof(mHandle->useCase));
219 } else if (mHandle->devices == AudioSystem::DEVICE_IN_FM_RX_A2DP) {
220 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(mHandle->useCase));
221#endif
222 } else if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)){
223 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, sizeof(mHandle->useCase));
224 } else {
225 strlcpy(mHandle->useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(mHandle->useCase));
226 }
227 }
228 free(use_case);
229 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
230 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
231#if 0
232 if((mDevices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
233 (mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)) {
234 mHandle->module->route(mHandle, (mDevices | AudioSystem::DEVICE_IN_PROXY) , AudioSystem::MODE_IN_COMMUNICATION);
235 }else
236#endif
237 {
238 mHandle->module->route(mHandle, mDevices , AudioSystem::MODE_IN_COMMUNICATION);
239 }
240 } else {
241#if 0
242
243 if((mHandle->devices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)||
244 (mHandle->devices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){
245 mHandle->module->route(mHandle, AudioSystem::DEVICE_IN_PROXY , mParent->mode());
246 } else
247#endif
248 {
249
250 mHandle->module->route(mHandle, mDevices , mParent->mode());
251 }
252 }
253 if (!strcmp(mHandle->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
254 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_FM_REC) ||
255 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) ||
256 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||
257 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_UL_DL_REC) ||
258 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_DL_REC) ||
259 !strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) {
260 snd_use_case_set(mHandle->ucMgr, "_verb", mHandle->useCase);
261 } else {
262 snd_use_case_set(mHandle->ucMgr, "_enamod", mHandle->useCase);
263 }
264 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
265 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
266 err = mHandle->module->startVoipCall(mHandle);
267 }
268 else
269 mHandle->module->open(mHandle);
270 if(mHandle->handle == NULL) {
271 LOGE("read:: PCM device open failed");
272 mParent->mLock.unlock();
273
274 return 0;
275 }
276#if 0
277 if((mHandle->devices == AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET)||
278 (mHandle->devices == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)){
279 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
280 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
281 mParent->musbRecordingState |= USBRECBIT_VOIPCALL;
282 } else {
283 mParent->startUsbRecordingIfNotStarted();
284 mParent->musbRecordingState |= USBRECBIT_REC;
285 }
286 }
287#endif
288 mParent->mLock.unlock();
289 }
290#if 0
291 if(((mDevices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
292 (mDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)) &&
293 (!mParent->musbRecordingState)) {
294 mParent->mLock.lock();
295 LOGD("Starting UsbRecording thread");
296 mParent->startUsbRecordingIfNotStarted();
297 if(!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL) ||
298 !strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP)) {
299 LOGD("Enabling voip recording bit");
300 mParent->musbRecordingState |= USBRECBIT_VOIPCALL;
301 }else{
302 LOGD("Enabling HiFi Recording bit");
303 mParent->musbRecordingState |= USBRECBIT_REC;
304 }
305 mParent->mLock.unlock();
306 }
307#endif
308 period_size = mHandle->periodSize;
309 int read_pending = bytes;
310
311#ifdef SSR_ENABLED
312 if (mSurroundObj) {
313 int processed = 0;
314 int processed_pending;
315 int samples = bytes >> 1;
316 void *buffer_start = buffer;
317 int period_bytes = mHandle->handle->period_size;
318 int period_samples = period_bytes >> 1;
319
320 do {
321 if (mSurroundOutputBufferIdx > 0) {
322 LOGV("AudioStreamInALSA::read() - copy processed output "
323 "to buffer, mSurroundOutputBufferIdx = %d",
324 mSurroundOutputBufferIdx);
325 // Copy processed output to buffer
326 processed_pending = mSurroundOutputBufferIdx;
327 if (processed_pending > (samples - processed)) {
328 processed_pending = (samples - processed);
329 }
330 memcpy(buffer, mSurroundOutputBuffer, processed_pending * sizeof(Word16));
331 buffer += processed_pending * sizeof(Word16);
332 processed += processed_pending;
333 if (mSurroundOutputBufferIdx > processed_pending) {
334 // Shift leftover samples to beginning of the buffer
335 memcpy(&mSurroundOutputBuffer[0],
336 &mSurroundOutputBuffer[processed_pending],
337 (mSurroundOutputBufferIdx - processed_pending) * sizeof(Word16));
338 }
339 mSurroundOutputBufferIdx -= processed_pending;
340 }
341
342 if (processed >= samples) {
343 LOGV("AudioStreamInALSA::read() - done processing buffer, "
344 "processed = %d", processed);
345 // Done processing this buffer
346 break;
347 }
348
349 // Fill input buffer until there is enough to process
350 read_pending = SSR_INPUT_FRAME_SIZE - mSurroundInputBufferIdx;
351 read = mSurroundInputBufferIdx;
352 while (mHandle->handle && read_pending > 0) {
353 n = pcm_read(mHandle->handle, &mSurroundInputBuffer[read],
354 period_bytes);
355 LOGV("pcm_read() returned n = %d buffer:%p size:%d", n, &mSurroundInputBuffer[read], period_bytes);
356 if (n && n != -EAGAIN) {
357 //Recovery part of pcm_read. TODO:split recovery.
358 return static_cast<ssize_t>(n);
359 }
360 else if (n < 0) {
361 // Recovery is part of pcm_write. TODO split is later.
362 return static_cast<ssize_t>(n);
363 }
364 else {
365 read_pending -= period_samples;
366 read += period_samples;
367 }
368 }
369
370
371 if (mFp_4ch) {
372 fwrite( mSurroundInputBuffer, 1,
373 SSR_INPUT_FRAME_SIZE * sizeof(Word16), mFp_4ch);
374 }
375
376 //apply ssr libs to conver 4ch to 6ch
377 surround_filters_intl_process(mSurroundObj,
378 &mSurroundOutputBuffer[mSurroundOutputBufferIdx],
379 (Word16 *)mSurroundInputBuffer);
380
381 // Shift leftover samples to beginning of input buffer
382 if (read_pending < 0) {
383 memcpy(&mSurroundInputBuffer[0],
384 &mSurroundInputBuffer[SSR_INPUT_FRAME_SIZE],
385 (-read_pending) * sizeof(Word16));
386 }
387 mSurroundInputBufferIdx = -read_pending;
388
389 if (mFp_6ch) {
390 fwrite( &mSurroundOutputBuffer[mSurroundOutputBufferIdx],
391 1, SSR_OUTPUT_FRAME_SIZE * sizeof(Word16), mFp_6ch);
392 }
393
394 mSurroundOutputBufferIdx += SSR_OUTPUT_FRAME_SIZE;
395 LOGV("do_while loop: processed=%d, samples=%d\n", processed, samples);
396 } while (mHandle->handle && processed < samples);
397 read = processed * sizeof(Word16);
398 buffer = buffer_start;
399 } else
400#endif
401 {
402
403 do {
404 if (read_pending < period_size) {
405 read_pending = period_size;
406 }
407
408 n = pcm_read(mHandle->handle, buffer,
409 period_size);
410 LOGV("pcm_read() returned n = %d", n);
411 if (n && (n == -EIO || n == -EAGAIN || n == -EPIPE || n == -EBADFD)) {
412 mParent->mLock.lock();
413 LOGW("pcm_read() returned error n %d, Recovering from error\n", n);
414 pcm_close(mHandle->handle);
415 mHandle->handle = NULL;
416 if((!strncmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL, strlen(SND_USE_CASE_VERB_IP_VOICECALL))) ||
417 (!strncmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP, strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) {
418 pcm_close(mHandle->rxHandle);
419 mHandle->rxHandle = NULL;
420 mHandle->module->startVoipCall(mHandle);
421 }
422 else
423 mHandle->module->open(mHandle);
424 mParent->mLock.unlock();
425 continue;
426 }
427 else if (n < 0) {
428 LOGD("pcm_read() returned n < 0");
429 return static_cast<ssize_t>(n);
430 }
431 else {
432 read += static_cast<ssize_t>((period_size));
433 read_pending -= period_size;
434 buffer += period_size;
435 }
436
437 } while (mHandle->handle && read < bytes);
438 }
439
440 return read;
441}
442
443status_t AudioStreamInALSA::dump(int fd, const Vector<String16>& args)
444{
445 return NO_ERROR;
446}
447
448status_t AudioStreamInALSA::open(int mode)
449{
450 Mutex::Autolock autoLock(mParent->mLock);
451
452 status_t status = ALSAStreamOps::open(mode);
453
454 return status;
455}
456
457status_t AudioStreamInALSA::close()
458{
459 Mutex::Autolock autoLock(mParent->mLock);
460
461 LOGD("close");
462 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
463 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
464 if((mParent->mVoipStreamCount)) {
465 LOGD("musbRecordingState: %d, mVoipStreamCount:%d",mParent->musbRecordingState,
466 mParent->mVoipStreamCount );
467 if(mParent->mVoipStreamCount == 1) {
468 LOGE("Deregistering VOIP Call bit, musbPlaybackState:%d,"
469 "musbRecordingState:%d", mParent->musbPlaybackState, mParent->musbRecordingState);
470 mParent->musbPlaybackState &= ~USBPLAYBACKBIT_VOIPCALL;
471 mParent->musbRecordingState &= ~USBRECBIT_VOIPCALL;
472 mParent->closeUsbRecordingIfNothingActive();
473 mParent->closeUsbPlaybackIfNothingActive();
474 }
475 return NO_ERROR;
476 }
477 mParent->mVoipStreamCount = 0;
478 mParent->mVoipMicMute = 0;
479 } else {
480 LOGD("Deregistering REC bit, musbRecordingState:%d", mParent->musbRecordingState);
481 mParent->musbRecordingState &= ~USBRECBIT_REC;
482 }
483#if 0
484 if (mParent->mFusion3Platform) {
485 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
486 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
487 csd_client_stop_record();
488 }
489 }
490#endif
491 LOGD("close");
492 mParent->closeUsbRecordingIfNothingActive();
493
494 ALSAStreamOps::close();
495
496#ifdef SSR_ENABLED
497 if (mSurroundObj) {
498 surround_filters_release(mSurroundObj);
499 if (mSurroundObj)
500 free(mSurroundObj);
501 mSurroundObj = NULL;
502 if (mRealCoeffs){
503 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
504 if (mRealCoeffs[i]) {
505 free(mRealCoeffs[i]);
506 mRealCoeffs[i] = NULL;
507 }
508 }
509 free(mRealCoeffs);
510 mRealCoeffs = NULL;
511 }
512 if (mImagCoeffs){
513 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
514 if (mImagCoeffs[i]) {
515 free(mImagCoeffs[i]);
516 mImagCoeffs[i] = NULL;
517 }
518 }
519 free(mImagCoeffs);
520 mImagCoeffs = NULL;
521 }
522 if (mSurroundOutputBuffer){
523 free(mSurroundOutputBuffer);
524 mSurroundOutputBuffer = NULL;
525 }
526 if (mSurroundInputBuffer) {
527 free(mSurroundInputBuffer);
528 mSurroundInputBuffer = NULL;
529 }
530
531 if ( mFp_4ch ) fclose(mFp_4ch);
532 if ( mFp_6ch ) fclose(mFp_6ch);
533
534 }
535#endif
536
537 return NO_ERROR;
538}
539
540status_t AudioStreamInALSA::standby()
541{
542 Mutex::Autolock autoLock(mParent->mLock);
543
544 LOGD("standby");
545
546 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_IP_VOICECALL)) ||
547 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_PLAY_VOIP))) {
548 return NO_ERROR;
549 }
550
551#if 0
552 LOGD("standby");
553 if (mParent->mFusion3Platform) {
554 if((!strcmp(mHandle->useCase, SND_USE_CASE_VERB_INCALL_REC)) ||
555 (!strcmp(mHandle->useCase, SND_USE_CASE_MOD_CAPTURE_VOICE))) {
556 LOGD(" into standby, stop record");
557 csd_client_stop_record();
558 }
559 }
560#endif
561 mHandle->module->standby(mHandle);
562
563 LOGD("Checking for musbRecordingState %d", mParent->musbRecordingState);
564 mParent->musbRecordingState &= ~USBRECBIT_REC;
565 mParent->closeUsbRecordingIfNothingActive();
566
567 return NO_ERROR;
568}
569
570void AudioStreamInALSA::resetFramesLost()
571{
572 mFramesLost = 0;
573}
574
575unsigned int AudioStreamInALSA::getInputFramesLost() const
576{
577 unsigned int count = mFramesLost;
578 // Stupid interface wants us to have a side effect of clearing the count
579 // but is defined as a const to prevent such a thing.
580 ((AudioStreamInALSA *)this)->resetFramesLost();
581 return count;
582}
583
584status_t AudioStreamInALSA::setAcousticParams(void *params)
585{
586 Mutex::Autolock autoLock(mParent->mLock);
587
588 return (status_t)NO_ERROR;
589}
590
591#ifdef SSR_ENABLED
592status_t AudioStreamInALSA::initSurroundSoundLibrary(unsigned long buffersize)
593{
594 int subwoofer = 0; // subwoofer channel assignment: default as first microphone input channel
595 int low_freq = 4; // frequency upper bound for subwoofer: frequency=(low_freq-1)/FFT_SIZE*samplingRate, default as 4
596 int high_freq = 100; // frequency upper bound for spatial processing: frequency=(high_freq-1)/FFT_SIZE*samplingRate, default as 100
597 int ret = 0;
598
599 mSurroundInputBufferIdx = 0;
600 mSurroundOutputBufferIdx = 0;
601
602 if ( mSurroundObj ) {
603 LOGE("ola filter library is already initialized");
604 return ALREADY_EXISTS;
605 }
606
607 // Allocate memory for input buffer
608 mSurroundInputBuffer = (Word16 *) calloc(2 * SSR_INPUT_FRAME_SIZE,
609 sizeof(Word16));
610 if ( !mSurroundInputBuffer ) {
611 LOGE("Memory allocation failure. Not able to allocate memory for surroundInputBuffer");
612 goto init_fail;
613 }
614
615 // Allocate memory for output buffer
616 mSurroundOutputBuffer = (Word16 *) calloc(2 * SSR_OUTPUT_FRAME_SIZE,
617 sizeof(Word16));
618 if ( !mSurroundOutputBuffer ) {
619 LOGE("Memory allocation failure. Not able to allocate memory for surroundOutputBuffer");
620 goto init_fail;
621 }
622
623 // Allocate memory for real and imag coeffs array
624 mRealCoeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
625 if ( !mRealCoeffs ) {
626 LOGE("Memory allocation failure during real Coefficient array");
627 goto init_fail;
628 }
629
630 mImagCoeffs = (Word16 **) calloc(COEFF_ARRAY_SIZE, sizeof(Word16 *));
631 if ( !mImagCoeffs ) {
632 LOGE("Memory allocation failure during imaginary Coefficient array");
633 goto init_fail;
634 }
635
636 if( readCoeffsFromFile() != NO_ERROR) {
637 LOGE("Error while loading coeffs from file");
638 goto init_fail;
639 }
640
641 //calculate the size of data to allocate for mSurroundObj
642 ret = surround_filters_init(NULL,
643 6, // Num output channel
644 4, // Num input channel
645 mRealCoeffs, // Coeffs hardcoded in header
646 mImagCoeffs, // Coeffs hardcoded in header
647 subwoofer,
648 low_freq,
649 high_freq,
650 NULL);
651
652 if ( ret > 0 ) {
653 LOGV("Allocating surroundObj size is %d", ret);
654 mSurroundObj = (void *)malloc(ret);
655 memset(mSurroundObj,0,ret);
656 if (NULL != mSurroundObj) {
657 //initialize after allocating the memory for mSurroundObj
658 ret = surround_filters_init(mSurroundObj,
659 6,
660 4,
661 mRealCoeffs,
662 mImagCoeffs,
663 subwoofer,
664 low_freq,
665 high_freq,
666 NULL);
667 if (0 != ret) {
668 LOGE("surround_filters_init failed with ret:%d",ret);
669 surround_filters_release(mSurroundObj);
670 goto init_fail;
671 }
672 } else {
673 LOGE("Allocationg mSurroundObj failed");
674 goto init_fail;
675 }
676 } else {
677 LOGE("surround_filters_init(mSurroundObj=Null) failed with ret: %d",ret);
678 goto init_fail;
679 }
680
681 (void) surround_filters_set_channel_map(mSurroundObj, chanMap);
682
683 return NO_ERROR;
684
685init_fail:
686 if (mSurroundObj) {
687 free(mSurroundObj);
688 mSurroundObj = NULL;
689 }
690 if (mSurroundOutputBuffer) {
691 free(mSurroundOutputBuffer);
692 mSurroundOutputBuffer = NULL;
693 }
694 if (mSurroundInputBuffer) {
695 free(mSurroundInputBuffer);
696 mSurroundInputBuffer = NULL;
697 }
698 if (mRealCoeffs){
699 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
700 if (mRealCoeffs[i]) {
701 free(mRealCoeffs[i]);
702 mRealCoeffs[i] = NULL;
703 }
704 }
705 free(mRealCoeffs);
706 mRealCoeffs = NULL;
707 }
708 if (mImagCoeffs){
709 for (int i =0; i<COEFF_ARRAY_SIZE; i++ ) {
710 if (mImagCoeffs[i]) {
711 free(mImagCoeffs[i]);
712 mImagCoeffs[i] = NULL;
713 }
714 }
715 free(mImagCoeffs);
716 mImagCoeffs = NULL;
717 }
718
719 return NO_MEMORY;
720
721}
722
723
724// Helper function to read coeffs from File and updates real and imaginary
725// coeff array member variable
726status_t AudioStreamInALSA::readCoeffsFromFile()
727{
728 FILE *flt1r;
729 FILE *flt2r;
730 FILE *flt3r;
731 FILE *flt4r;
732 FILE *flt1i;
733 FILE *flt2i;
734 FILE *flt3i;
735 FILE *flt4i;
736
737 if ( (flt1r = fopen(SURROUND_FILE_1R, "rb")) == NULL ) {
738 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_1R);
739 return NAME_NOT_FOUND;
740 }
741
742 if ( (flt2r = fopen(SURROUND_FILE_2R, "rb")) == NULL ) {
743 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_2R);
744 return NAME_NOT_FOUND;
745 }
746
747 if ( (flt3r = fopen(SURROUND_FILE_3R, "rb")) == NULL ) {
748 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_3R);
749 return NAME_NOT_FOUND;
750 }
751
752 if ( (flt4r = fopen(SURROUND_FILE_4R, "rb")) == NULL ) {
753 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_4R);
754 return NAME_NOT_FOUND;
755 }
756
757 if ( (flt1i = fopen(SURROUND_FILE_1I, "rb")) == NULL ) {
758 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_1I);
759 return NAME_NOT_FOUND;
760 }
761
762 if ( (flt2i = fopen(SURROUND_FILE_2I, "rb")) == NULL ) {
763 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_2I);
764 return NAME_NOT_FOUND;
765 }
766
767 if ( (flt3i = fopen(SURROUND_FILE_3I, "rb")) == NULL ) {
768 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_3I);
769 return NAME_NOT_FOUND;
770 }
771
772 if ( (flt4i = fopen(SURROUND_FILE_4I, "rb")) == NULL ) {
773 LOGE("Cannot open filter co-efficient file %s", SURROUND_FILE_4I);
774 return NAME_NOT_FOUND;
775 }
776 LOGV("readCoeffsFromFile all filter files opened");
777
778 for (int i=0; i<COEFF_ARRAY_SIZE; i++) {
779 mRealCoeffs[i] = (Word16 *)calloc(FILT_SIZE, sizeof(Word16));
780 }
781 for (int i=0; i<COEFF_ARRAY_SIZE; i++) {
782 mImagCoeffs[i] = (Word16 *)calloc(FILT_SIZE, sizeof(Word16));
783 }
784
785 // Read real co-efficients
786 if (NULL != mRealCoeffs[0]) {
787 fread(mRealCoeffs[0], sizeof(int16), FILT_SIZE, flt1r);
788 }
789 if (NULL != mRealCoeffs[0]) {
790 fread(mRealCoeffs[1], sizeof(int16), FILT_SIZE, flt2r);
791 }
792 if (NULL != mRealCoeffs[0]) {
793 fread(mRealCoeffs[2], sizeof(int16), FILT_SIZE, flt3r);
794 }
795 if (NULL != mRealCoeffs[0]) {
796 fread(mRealCoeffs[3], sizeof(int16), FILT_SIZE, flt4r);
797 }
798
799 // read imaginary co-efficients
800 if (NULL != mImagCoeffs[0]) {
801 fread(mImagCoeffs[0], sizeof(int16), FILT_SIZE, flt1i);
802 }
803 if (NULL != mImagCoeffs[0]) {
804 fread(mImagCoeffs[1], sizeof(int16), FILT_SIZE, flt2i);
805 }
806 if (NULL != mImagCoeffs[0]) {
807 fread(mImagCoeffs[2], sizeof(int16), FILT_SIZE, flt3i);
808 }
809 if (NULL != mImagCoeffs[0]) {
810 fread(mImagCoeffs[3], sizeof(int16), FILT_SIZE, flt4i);
811 }
812
813 fclose(flt1r);
814 fclose(flt2r);
815 fclose(flt3r);
816 fclose(flt4r);
817 fclose(flt1i);
818 fclose(flt2i);
819 fclose(flt3i);
820 fclose(flt4i);
821
822 return NO_ERROR;
823}
824#endif
825
826} // namespace android_audio_legacy