blob: dc973b48f4b3693cd82fe7901b34df3a4bb50063
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <string.h> |
4 | #include <fcntl.h> |
5 | #include <malloc.h> |
6 | #include <unistd.h> |
7 | #include <pthread.h> |
8 | #include <sys/stat.h> |
9 | #include <media/mediarecorder.h> |
10 | #include <system/audio.h> |
11 | #include <android/log.h> |
12 | #include <cutils/properties.h> |
13 | #include <media/AudioSystem.h> |
14 | #include <sys/prctl.h> |
15 | #include <math.h> |
16 | |
17 | #include "audio_cfg.h" |
18 | #include "audio_api.h" |
19 | #include "audio_android.h" |
20 | #include "audio_android_effect.h" |
21 | |
22 | #define msleep(x) usleep(x*1000) |
23 | |
24 | #define LOG_TAG "AndroidAudio" |
25 | #include "CTvLog.h" |
26 | |
27 | #define SOFTWARE_RESAMPLE |
28 | |
29 | #define HDMI_PERIOD_SIZE 1024 |
30 | #define PERIOD_SIZE 512 |
31 | |
32 | #define debug 0 |
33 | //temp buffer between record thread and playback thread |
34 | #define temp_buffer_size 1024*14 |
35 | #define mid_buffer_size 1024*7 //reset distance for HDMI |
36 | #define reset_distance 1024*2 //reset distance for atv |
37 | |
38 | |
39 | #ifdef SOFTWARE_RESAMPLE |
40 | #define Upresample_distance 1024*10 |
41 | #define Downresample_distance 1024*4 |
42 | |
43 | #define period_size 2 //1024*periodsize |
44 | #define resample_ratio 16 // unit:one in a thousand |
45 | #define fraction_bit 16 //16.16 type |
46 | #define upsample_framecount (1024 + resample_ratio) |
47 | #define upsample_ratio (unsigned int)((float)downsample_framecount*65536.0f/(float)1024) |
48 | #define downsample_framecount (1024 - resample_ratio) |
49 | #define downsample_ratio (unsigned int)((float)upsample_framecount*65536.0f/(float)1024) |
50 | #define resample_counter (1024/resample_ratio) |
51 | |
52 | short *resample_temp_buffer = NULL; |
53 | |
54 | const unsigned int FractionStep_up = upsample_ratio; |
55 | const unsigned int FractionStep_down = downsample_ratio; |
56 | unsigned int Upsample_Fraction = 0; |
57 | unsigned int Downsample_Fraction = 0; |
58 | #endif |
59 | |
60 | #if debug == 1 |
61 | int record_counter = 0; |
62 | int playback_counter = 0; |
63 | #endif |
64 | |
65 | |
66 | #define HISTORY_BASE (12) |
67 | #define HISTORY_NUM (1<<12) |
68 | static signed history[2][HISTORY_NUM]; |
69 | |
70 | //showbo |
71 | static const int CC_AUDIO_SOURCE_IN_HDMI = 0;//just test,not true value |
72 | |
73 | CAndroidAudio::CAndroidAudio(CAudioAlsa *p): mpAudioAlsa(p) |
74 | { |
75 | int mDumpDataFlag = 0; |
76 | int mDumpDataFd = -1; |
77 | mlpRecorder = NULL; |
78 | mlpTracker = NULL; |
79 | temp_buffer = NULL; |
80 | end_temp_buffer = NULL; |
81 | record_write_pointer = NULL; |
82 | playback_read_pointer = NULL; |
83 | gEnableNoiseGate = false; |
84 | gUserSetEnableNoiseGate = false; |
85 | zero_count_left = 2000; |
86 | zero_count_right = 2000; |
87 | NOISE_HIS = 48000 * 5; |
88 | gNoiseGateThresh = 0; |
89 | } |
90 | CAndroidAudio::~CAndroidAudio() |
91 | { |
92 | } |
93 | |
94 | void CAndroidAudio::noise_filter_init() |
95 | { |
96 | memset(history, 0, sizeof(history)); |
97 | zero_count_left = 2000; |
98 | zero_count_right = 2000; |
99 | } |
100 | |
101 | signed CAndroidAudio::noise_filter_left(signed sample) |
102 | { |
103 | //if(!enable_noise_filter ||hdmi_src_in) |
104 | // return sample; |
105 | signed sum_left = 0; |
106 | signed sum_right = 0; |
107 | unsigned left_pos = 0; |
108 | unsigned right_pos = 0; |
109 | signed y = 0; |
110 | int i = 0; |
111 | signed sum = 0; |
112 | signed ret_sample; |
113 | signed zero = 0; |
114 | sample <<= 16; |
115 | sample >>= 16; |
116 | #if 0 |
117 | if(hdmi_src_in) { //for hdmi src,not use filter and -6db for prevent clip of SRS/other post process. |
118 | ret_sample = Mul28(sample, M3DB); |
119 | return ret_sample; |
120 | } else { |
121 | ret_sample = Mul28(sample, M3DB); |
122 | sample = ret_sample; |
123 | } |
124 | #endif |
125 | sum_left -= history[0][left_pos]; |
126 | sum_left += history[0][(left_pos + HISTORY_NUM - 1) |
127 | & ((1 << HISTORY_BASE) - 1)]; |
128 | sum = sum_left >> HISTORY_BASE; |
129 | left_pos = (left_pos + 1) & ((1 << HISTORY_BASE) - 1); |
130 | history[0][(left_pos + HISTORY_NUM - 1) & ((1 << HISTORY_BASE) - 1)] = |
131 | sample; |
132 | |
133 | zero = abs(sample - sum); |
134 | if (zero < gNoiseGateThresh) { |
135 | zero_count_left++; |
136 | if (zero_count_left > NOISE_HIS) { |
137 | zero_count_left = NOISE_HIS; |
138 | y = 0; |
139 | } else { |
140 | y = sample; |
141 | } |
142 | } else { |
143 | y = sample; |
144 | zero_count_left = 0; |
145 | } |
146 | return y; |
147 | } |
148 | |
149 | signed CAndroidAudio::noise_filter_right(signed sample) |
150 | { |
151 | //if(!enable_noise_filter ||hdmi_src_in) |
152 | // return sample; |
153 | signed y = 0; |
154 | int i = 0; |
155 | signed ret_sample; |
156 | signed sum = 0; |
157 | sample <<= 16; |
158 | sample >>= 16; |
159 | #if 0 |
160 | if(hdmi_src_in) { //for hdmi src,not use filter and -6db for prevent clip of SRS/other post process. |
161 | ret_sample = Mul28(sample, M3DB); |
162 | return ret_sample; |
163 | } else { |
164 | ret_sample = Mul28(sample, M3DB); |
165 | sample = ret_sample; |
166 | } |
167 | #endif |
168 | sum_right -= history[1][right_pos]; |
169 | sum_right += history[1][(right_pos + HISTORY_NUM - 1) |
170 | & ((1 << HISTORY_BASE) - 1)]; |
171 | sum = sum_right >> HISTORY_BASE; |
172 | right_pos = (right_pos + 1) & ((1 << HISTORY_BASE) - 1); |
173 | history[1][(right_pos + HISTORY_NUM - 1) & ((1 << HISTORY_BASE) - 1)] = |
174 | sample; |
175 | |
176 | if (abs(sample - sum) < gNoiseGateThresh) { |
177 | zero_count_right++; |
178 | if (zero_count_right > NOISE_HIS) { |
179 | zero_count_right = NOISE_HIS; |
180 | y = 0; |
181 | } else { |
182 | y = sample; |
183 | } |
184 | } else { |
185 | y = sample; |
186 | zero_count_right = 0; |
187 | } |
188 | return y; |
189 | } |
190 | |
191 | void CAndroidAudio::DeleteAudioRecorder(void) |
192 | { |
193 | #if ANDROID_PLATFORM_SDK_VERSION < 19 |
194 | if (mlpRecorder != NULL) { |
195 | delete mlpRecorder; |
196 | mlpRecorder = NULL; |
197 | } |
198 | #else |
199 | if (mlpRecorder != NULL ) { |
200 | mlpRecorder = NULL; |
201 | } |
202 | |
203 | if (mmpAudioRecorder != NULL ) { |
204 | mmpAudioRecorder.clear(); |
205 | } |
206 | #endif |
207 | } |
208 | |
209 | void CAndroidAudio::FreeAudioRecorder(void) |
210 | { |
211 | if (mlpRecorder != NULL) { |
212 | mlpRecorder->stop(); |
213 | } |
214 | |
215 | DeleteAudioRecorder(); |
216 | } |
217 | |
218 | void CAndroidAudio::DeleteAudioTracker(void) |
219 | { |
220 | #if ANDROID_PLATFORM_SDK_VERSION < 19 |
221 | if (mlpTracker != NULL) { |
222 | delete mlpTracker; |
223 | mlpTracker = NULL; |
224 | } |
225 | #else |
226 | if (mlpTracker != NULL ) { |
227 | mlpTracker = NULL; |
228 | } |
229 | |
230 | if (mmpAudioTracker != NULL ) { |
231 | mmpAudioTracker.clear(); |
232 | } |
233 | #endif |
234 | } |
235 | |
236 | void CAndroidAudio::FreeAudioTracker(void) |
237 | { |
238 | if (mlpTracker != NULL) { |
239 | mlpTracker->stop(); |
240 | } |
241 | |
242 | DeleteAudioTracker(); |
243 | } |
244 | |
245 | int CAndroidAudio::InitTempBuffer() |
246 | { |
247 | int tmp_size = 0; |
248 | |
249 | if (NULL == temp_buffer) { |
250 | tmp_size = temp_buffer_size; |
251 | temp_buffer = new short[tmp_size]; |
252 | if (NULL == temp_buffer) { |
253 | return -1; |
254 | } |
255 | memset(temp_buffer, 0, tmp_size * sizeof(short)); |
256 | end_temp_buffer = temp_buffer + tmp_size; |
257 | record_write_pointer = temp_buffer; |
258 | playback_read_pointer = temp_buffer; |
259 | } |
260 | #ifdef SOFTWARE_RESAMPLE |
261 | if (NULL == resample_temp_buffer) { |
262 | tmp_size = upsample_framecount * 2 * period_size + 10; |
263 | resample_temp_buffer = new short[tmp_size]; |
264 | if (NULL == resample_temp_buffer) { |
265 | return -1; |
266 | } |
267 | memset(temp_buffer, 0, tmp_size * sizeof(short)); |
268 | } |
269 | #endif |
270 | return 0; |
271 | } |
272 | |
273 | static void MuteTempBuffer() |
274 | { |
275 | if ((NULL != temp_buffer) && (NULL != mlpTracker)) { |
276 | playback_read_pointer = record_write_pointer; |
277 | memset(temp_buffer, 0, temp_buffer_size * sizeof(short)); |
278 | for (int i = 0; i < 10; i++) { |
279 | mlpTracker->write(temp_buffer, temp_buffer_size); |
280 | } |
281 | } |
282 | } |
283 | |
284 | void CAndroidAudio::FreeTempBuffer() |
285 | { |
286 | if (temp_buffer != NULL) { |
287 | delete[] temp_buffer; |
288 | temp_buffer = NULL; |
289 | end_temp_buffer = NULL; |
290 | record_write_pointer = NULL; |
291 | playback_read_pointer = NULL; |
292 | } |
293 | #ifdef SOFTWARE_RESAMPLE |
294 | if (resample_temp_buffer != NULL) { |
295 | delete[] resample_temp_buffer; |
296 | resample_temp_buffer = NULL; |
297 | } |
298 | #endif |
299 | } |
300 | |
301 | void CAndroidAudio::ResetRecordWritePointer() |
302 | { |
303 | record_write_pointer = playback_read_pointer; |
304 | } |
305 | |
306 | void CAndroidAudio::ResetPlaybackReadPointer() |
307 | { |
308 | record_write_pointer = playback_read_pointer; |
309 | } |
310 | |
311 | void CAndroidAudio::ResetPointer() |
312 | { |
313 | if (mpAudioAlsa->GetAudioInSource() == CC_AUDIO_SOURCE_IN_HDMI) { |
314 | playback_read_pointer = record_write_pointer - mid_buffer_size; |
315 | if (playback_read_pointer < temp_buffer) { |
316 | playback_read_pointer += temp_buffer_size; |
317 | } |
318 | } else { |
319 | playback_read_pointer = record_write_pointer - reset_distance; |
320 | if (playback_read_pointer < temp_buffer) { |
321 | playback_read_pointer += temp_buffer_size; |
322 | } |
323 | } |
324 | } |
325 | |
326 | // 0: LINEIN 1: HDMI |
327 | void CAndroidAudio::reset_system_framesize(int input_sample_rate, int output_sample_rate) |
328 | { |
329 | int frame_size = 0; |
330 | |
331 | audio_io_handle_t handle = -1; |
332 | |
333 | if (mpAudioAlsa->GetAudioInSource() == CC_AUDIO_SOURCE_IN_HDMI) { |
334 | frame_size = HDMI_PERIOD_SIZE * 4; |
335 | LOGE("Source In:HDMI, Android system audio out framecount: %d \n", |
336 | frame_size); |
337 | } else { |
338 | //msleep(500); |
339 | frame_size = PERIOD_SIZE * 4; |
340 | LOGE("Source In:LIENIN, Android system audio out framecount: %d \n", |
341 | frame_size); |
342 | } |
343 | |
344 | handle = AudioSystem::getInput(AUDIO_SOURCE_MIC, input_sample_rate, |
345 | AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 0); |
346 | |
347 | if (handle > 0) { |
348 | char str[64]; |
349 | memset(str, 0, sizeof(str)); |
350 | sprintf(str, "frame_count=%d", frame_size); |
351 | LOGE("input handle number: %d \n", handle); |
352 | AudioSystem::setParameters(handle, String8(str)); |
353 | } else { |
354 | LOGE("Can't get input handle! \n"); |
355 | } |
356 | |
357 | handle = -1; |
358 | |
359 | handle = AudioSystem::getOutput(AUDIO_STREAM_MUSIC, output_sample_rate, |
360 | AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, |
361 | AUDIO_OUTPUT_FLAG_NONE); |
362 | |
363 | if (handle > 0) { |
364 | char str[64]; |
365 | memset(str, 0, sizeof(str)); |
366 | sprintf(str, "frame_count=%d", frame_size); |
367 | LOGE("output handle number: %d \n", handle); |
368 | AudioSystem::setParameters(handle, String8(str)); |
369 | } else { |
370 | LOGE("Can't get output handle! \n"); |
371 | } |
372 | } |
373 | |
374 | inline short CAndroidAudio::clip(int x) //Clip from 16.16 fixed-point to 0.15 fixed-point. |
375 | { |
376 | if (x < -32768) |
377 | return -32768; |
378 | else if (x > 32767) |
379 | return 32767; |
380 | else |
381 | return x; |
382 | } |
383 | |
384 | int CAndroidAudio::upsample(short *input, short *output, unsigned int FractionStep, |
385 | unsigned int input_frame_size, unsigned int frac) |
386 | { |
387 | unsigned int inputIndex = 1; |
388 | unsigned int outputIndex = 0; |
389 | |
390 | while (inputIndex < input_frame_size) { |
391 | *output++ = clip( |
392 | input[2 * inputIndex - 2] |
393 | + (((input[2 * inputIndex] - input[2 * inputIndex - 2]) |
394 | * (int32_t) frac) >> 16)); |
395 | *output++ = clip( |
396 | input[2 * inputIndex - 1] |
397 | + (((input[2 * inputIndex + 1] |
398 | - input[2 * inputIndex - 1]) * (int32_t) frac) |
399 | >> 16)); |
400 | |
401 | frac += FractionStep; |
402 | inputIndex += (frac >> 16); |
403 | frac = (frac & 0xffff); |
404 | outputIndex++; |
405 | } |
406 | |
407 | return outputIndex; |
408 | } |
409 | |
410 | int CAndroidAudio::downsample(short *input, short *output, unsigned int FractionStep, |
411 | unsigned int input_frame_size, unsigned int frac) |
412 | { |
413 | unsigned int inputIndex = 1; |
414 | unsigned int outputIndex = 0; |
415 | |
416 | while (inputIndex < input_frame_size) { |
417 | *output++ = clip( |
418 | input[2 * inputIndex - 2] |
419 | + (((input[2 * inputIndex] - input[2 * inputIndex - 2]) |
420 | * (int32_t) frac) >> 16)); |
421 | *output++ = clip( |
422 | input[2 * inputIndex - 1] |
423 | + (((input[2 * inputIndex + 1] |
424 | - input[2 * inputIndex - 1]) * (int32_t) frac) |
425 | >> 16)); |
426 | |
427 | frac += FractionStep; |
428 | inputIndex += (frac >> 16); |
429 | frac = (frac & 0xffff); |
430 | outputIndex++; |
431 | } |
432 | |
433 | return outputIndex; |
434 | } |
435 | |
436 | int CAndroidAudio::GetWriteSpace(short volatile *WritePoint, |
437 | short volatile *ReadPoint) |
438 | { |
439 | unsigned int space; |
440 | |
441 | if (WritePoint >= ReadPoint) |
442 | space = temp_buffer_size - (WritePoint - ReadPoint); |
443 | else |
444 | space = ReadPoint - WritePoint; |
445 | |
446 | return space; |
447 | } |
448 | int CAndroidAudio::GetReadSpace(short volatile *WritePoint, short volatile *ReadPoint) |
449 | { |
450 | unsigned int space; |
451 | |
452 | if (WritePoint >= ReadPoint) |
453 | space = WritePoint - ReadPoint; |
454 | else |
455 | space = temp_buffer_size - (ReadPoint - WritePoint); |
456 | |
457 | return space; |
458 | } |
459 | |
460 | void CAndroidAudio::recorderCallback(int event, void *user, void *info) |
461 | { |
462 | if (AudioRecord::EVENT_MORE_DATA == event) { |
463 | AudioRecord::Buffer *pbuf = (AudioRecord::Buffer *) info; |
464 | |
465 | if (NULL == mlpRecorder) |
466 | return; |
467 | |
468 | unsigned int offset_bytes = 2 |
469 | * (end_temp_buffer - record_write_pointer); |
470 | unsigned int copy_bytes; |
471 | unsigned int output_bytes; |
472 | |
473 | int available_write_space; |
474 | available_write_space = GetWriteSpace(record_write_pointer, |
475 | playback_read_pointer); |
476 | |
477 | //LOGE("~~~~~available_write_space = %d \n", available_write_space); |
478 | |
479 | if (available_write_space < pbuf->size / 2) { |
480 | LOGE( |
481 | "[%s]: ***** FULL! *****\n\trd=0x%x, wr=0x%x, wr_lvl = 0x%x, wr_req = 0x%x\n", |
482 | __FUNCTION__, playback_read_pointer, record_write_pointer, |
483 | available_write_space, pbuf->size / 2); |
484 | |
485 | if (mpAudioAlsa->GetAudioInSource() == CC_AUDIO_SOURCE_IN_HDMI) { |
486 | playback_read_pointer += mid_buffer_size; |
487 | if (playback_read_pointer >= end_temp_buffer) { |
488 | playback_read_pointer -= temp_buffer_size; |
489 | } |
490 | } else { |
491 | playback_read_pointer += (temp_buffer_size - reset_distance); |
492 | if (playback_read_pointer >= end_temp_buffer) { |
493 | playback_read_pointer -= temp_buffer_size; |
494 | } |
495 | } |
496 | return; |
497 | } |
498 | #if debug == 1 |
499 | if(record_counter > 500) { |
500 | LOGE("~~~~~RecordCallback, pbuf->size:%d, pbuf->frameCount:%d", pbuf->size, pbuf->frameCount); |
501 | record_counter = 0; |
502 | } else { |
503 | record_counter++; |
504 | } |
505 | #endif |
506 | |
507 | #ifdef SOFTWARE_RESAMPLE |
508 | if (mpAudioAlsa->GetAudioInSource() == CC_AUDIO_SOURCE_IN_HDMI) { |
509 | if (available_write_space <= Downresample_distance) { |
510 | output_bytes = 4 |
511 | * downsample((short *) pbuf->raw, resample_temp_buffer, |
512 | FractionStep_down, pbuf->frameCount, |
513 | Downsample_Fraction); |
514 | |
515 | LOGE( |
516 | "downsample: output_framecount = %d, input_frameCount = %d\n", |
517 | output_bytes / 4, pbuf->frameCount); |
518 | |
519 | if (offset_bytes >= output_bytes) { |
520 | memcpy((short *) record_write_pointer, resample_temp_buffer, |
521 | output_bytes); |
522 | record_write_pointer += output_bytes / 2; |
523 | |
524 | if (record_write_pointer == end_temp_buffer) |
525 | record_write_pointer = temp_buffer; |
526 | } else { |
527 | memcpy((short *) record_write_pointer, resample_temp_buffer, |
528 | offset_bytes); |
529 | copy_bytes = offset_bytes; |
530 | offset_bytes = output_bytes - copy_bytes; |
531 | record_write_pointer = temp_buffer; |
532 | memcpy((short *) record_write_pointer, |
533 | resample_temp_buffer + (copy_bytes / 2), |
534 | offset_bytes); |
535 | record_write_pointer += offset_bytes / 2; |
536 | } |
537 | return; |
538 | } else if (available_write_space >= Upresample_distance) { |
539 | output_bytes = 4 |
540 | * upsample((short *) pbuf->raw, resample_temp_buffer, |
541 | FractionStep_up, pbuf->frameCount, |
542 | Upsample_Fraction); |
543 | |
544 | LOGE( |
545 | "upsample: output_framecount = %d, input_frameCount = %d\n", |
546 | output_bytes / 4, pbuf->frameCount); |
547 | |
548 | if (offset_bytes >= output_bytes) { |
549 | memcpy((short *) record_write_pointer, resample_temp_buffer, |
550 | output_bytes); |
551 | record_write_pointer += output_bytes / 2; |
552 | |
553 | if (record_write_pointer == end_temp_buffer) |
554 | record_write_pointer = temp_buffer; |
555 | } else { |
556 | memcpy((short *) record_write_pointer, resample_temp_buffer, |
557 | offset_bytes); |
558 | copy_bytes = offset_bytes; |
559 | offset_bytes = output_bytes - copy_bytes; |
560 | record_write_pointer = temp_buffer; |
561 | memcpy((short *) record_write_pointer, |
562 | resample_temp_buffer + (copy_bytes / 2), |
563 | offset_bytes); |
564 | record_write_pointer += offset_bytes / 2; |
565 | } |
566 | return; |
567 | } |
568 | |
569 | Upsample_Fraction = 0; |
570 | Downsample_Fraction = 0; |
571 | } |
572 | #endif |
573 | |
574 | if (offset_bytes >= pbuf->size) { |
575 | memcpy((short *) record_write_pointer, pbuf->raw, pbuf->size); |
576 | record_write_pointer += pbuf->size / 2; |
577 | |
578 | if (record_write_pointer == end_temp_buffer) |
579 | record_write_pointer = temp_buffer; |
580 | } else { |
581 | memcpy((short *) record_write_pointer, pbuf->raw, offset_bytes); |
582 | copy_bytes = offset_bytes; |
583 | offset_bytes = pbuf->size - copy_bytes; |
584 | record_write_pointer = temp_buffer; |
585 | memcpy((short *) record_write_pointer, |
586 | (short *) pbuf->raw + (copy_bytes / 2), offset_bytes); |
587 | record_write_pointer += offset_bytes / 2; |
588 | } |
589 | |
590 | //LOGD("--------RecordCallback, pbuf->size:%d, pbuf->frameCount:%d\n", pbuf->size, pbuf->frameCount); |
591 | //LOGD("--------Record----offset_bytes:%d\n", 2*(record_write_pointer-temp_buffer)); |
592 | |
593 | } else if (AudioRecord::EVENT_OVERRUN == event) { |
594 | LOGE("[%s]: AudioRecord::EVENT_OVERRUN\n", __FUNCTION__); |
595 | } else if (AudioRecord::EVENT_MARKER == event) { |
596 | LOGD("[%s]: AudioRecord::EVENT_MARKER\n", __FUNCTION__); |
597 | } else if (AudioRecord::EVENT_NEW_POS == event) { |
598 | LOGD("[%s]: AudioRecord::EVENT_NEW_POS\n", __FUNCTION__); |
599 | } |
600 | } |
601 | |
602 | void CAndroidAudio::trackerCallback(int event, void *user, void *info) |
603 | { |
604 | if (AudioTrack::EVENT_MORE_DATA == event) { |
605 | AudioTrack::Buffer *pbuf = (AudioTrack::Buffer *) info; |
606 | |
607 | if (NULL == mlpTracker) |
608 | return; |
609 | |
610 | int available_read_space; |
611 | available_read_space = GetReadSpace(record_write_pointer, |
612 | playback_read_pointer); |
613 | |
614 | //LOGE("~~~~~available_read_space = %d input_bytes = %d \n", available_read_space,input_bytes); |
615 | |
616 | if (available_read_space < pbuf->size / 2) { |
617 | LOGE( |
618 | "[%s]: ***** EMPTY *****\n\trd=0x%x, wr=0x%x, rd_lvl=0x%x, rd_req=0x%x*****\n", |
619 | __FUNCTION__, playback_read_pointer, record_write_pointer, |
620 | available_read_space, pbuf->size / 2); |
621 | |
622 | if (mpAudioAlsa->GetAudioInSource() == CC_AUDIO_SOURCE_IN_HDMI) { |
623 | playback_read_pointer -= mid_buffer_size; |
624 | if (playback_read_pointer < temp_buffer) |
625 | playback_read_pointer += temp_buffer_size; |
626 | } else { |
627 | playback_read_pointer -= reset_distance; |
628 | if (playback_read_pointer < temp_buffer) |
629 | playback_read_pointer += temp_buffer_size; |
630 | } |
631 | |
632 | } else { |
633 | unsigned int offset_bytes = 2 |
634 | * (end_temp_buffer - playback_read_pointer); |
635 | unsigned int copy_bytes; |
636 | int sampNum; |
637 | |
638 | if (offset_bytes >= pbuf->size) { |
639 | if (gEnableNoiseGate) { |
640 | sampNum = pbuf->size / 2; |
641 | for (int i = 0; i < sampNum; i++) { |
642 | pbuf->i16[i] = (short) noise_filter_left( |
643 | (signed) (playback_read_pointer[i])); |
644 | i++; |
645 | pbuf->i16[i] = (short) noise_filter_left( |
646 | (signed) (playback_read_pointer[i])); |
647 | } |
648 | } else { |
649 | memcpy(pbuf->raw, (short *) playback_read_pointer, |
650 | pbuf->size); |
651 | } |
652 | |
653 | memset((void *) playback_read_pointer, 0, pbuf->size); |
654 | playback_read_pointer += pbuf->size / 2; |
655 | |
656 | if (playback_read_pointer == end_temp_buffer) |
657 | playback_read_pointer = temp_buffer; |
658 | } else { |
659 | if (gEnableNoiseGate) { |
660 | sampNum = offset_bytes / 2; |
661 | for (int i = 0; i < sampNum; i++) { |
662 | pbuf->i16[i] = (short) noise_filter_left( |
663 | (signed) (playback_read_pointer[i])); |
664 | i++; |
665 | pbuf->i16[i] = (short) noise_filter_left( |
666 | (signed) (playback_read_pointer[i])); |
667 | } |
668 | } else { |
669 | memcpy(pbuf->raw, (short *) playback_read_pointer, |
670 | offset_bytes); |
671 | } |
672 | |
673 | memset((void *) playback_read_pointer, 0, offset_bytes); |
674 | copy_bytes = offset_bytes; |
675 | offset_bytes = pbuf->size - copy_bytes; |
676 | playback_read_pointer = temp_buffer; |
677 | |
678 | if (gEnableNoiseGate) { |
679 | short *pSrcPtr = &(pbuf->i16[copy_bytes / 2]); |
680 | sampNum = offset_bytes / 2; |
681 | for (int i = 0; i < sampNum; i++) { |
682 | pSrcPtr[i] = (short) noise_filter_left( |
683 | (signed) (playback_read_pointer[i])); |
684 | i++; |
685 | pSrcPtr[i] = (short) noise_filter_left( |
686 | (signed) (playback_read_pointer[i])); |
687 | } |
688 | } else { |
689 | memcpy((short *) pbuf->raw + (copy_bytes / 2), |
690 | (short *) playback_read_pointer, offset_bytes); |
691 | } |
692 | memset((void *) playback_read_pointer, 0, offset_bytes); |
693 | playback_read_pointer += offset_bytes / 2; |
694 | } |
695 | DoDumpData(pbuf->raw, pbuf->size); |
696 | |
697 | #if debug == 1 |
698 | if(playback_counter > 500) { |
699 | LOGE("----PlaybackCallback, pbuf->size:%d, pbuf->frameCount:%d", pbuf->size, pbuf->frameCount); |
700 | playback_counter = 0; |
701 | } else { |
702 | playback_counter++; |
703 | } |
704 | #endif |
705 | |
706 | } |
707 | //LOGE("---Playback---offset_bytes:%d\n", 2*(playback_read_pointer-temp_buffer)); |
708 | } else if (AudioTrack::EVENT_UNDERRUN == event) { |
709 | LOGE("[%s]: AudioTrack::EVENT_UNDERRUN\n", __FUNCTION__); |
710 | } else if (AudioTrack::EVENT_LOOP_END == event) { |
711 | LOGD("[%s]: AudioTrack::EVENT_LOOP_END\n", __FUNCTION__); |
712 | } else if (AudioTrack::EVENT_MARKER == event) { |
713 | LOGD("[%s]: AudioTrack::EVENT_MARKER\n", __FUNCTION__); |
714 | } else if (AudioTrack::EVENT_NEW_POS == event) { |
715 | LOGD("[%s]: AudioTrack::EVENT_NEW_POS\n", __FUNCTION__); |
716 | } else if (AudioTrack::EVENT_BUFFER_END == event) { |
717 | LOGD("[%s]: AudioTrack::EVENT_BUFFER_END\n", __FUNCTION__); |
718 | } |
719 | } |
720 | |
721 | int CAndroidAudio::initAudioTracker(int sr) |
722 | { |
723 | status_t ret; |
724 | int tmp_session_id = 0; |
725 | |
726 | if (NULL != mlpTracker) { |
727 | LOGE("[%s:%d] Trying to new AudioTrack while it's still not NULL.\n", |
728 | __FUNCTION__, __LINE__); |
729 | goto err_exit; |
730 | } |
731 | |
732 | #if ANDROID_PLATFORM_SDK_VERSION < 19 |
733 | mlpTracker = new AudioTrack(); |
734 | if (NULL == mlpTracker) { |
735 | LOGE("[%s:%d] Failed to new AudioTrack.\n", __FUNCTION__, __LINE__); |
736 | goto err_exit; |
737 | } |
738 | #else |
739 | mmpAudioTracker = new AudioTrack(); |
740 | mlpTracker = mmpAudioTracker.get(); |
741 | #endif |
742 | |
743 | tmp_session_id = amAndroidGetAudioSessionId(); |
744 | ret = mlpTracker->set(AUDIO_STREAM_DEFAULT, //inputSource |
745 | sr, //sampleRate |
746 | AUDIO_FORMAT_PCM_16_BIT, //format |
747 | AUDIO_CHANNEL_IN_STEREO, //channelMask |
748 | 0, //frameCount |
749 | AUDIO_OUTPUT_FLAG_NONE, //flags |
750 | trackerCallback, //trackerCallback, |
751 | NULL, //user when callback |
752 | 0, //notificationFrames |
753 | NULL, //shared buffer |
754 | false, //threadCanCallJava |
755 | tmp_session_id //sessionId |
756 | ); |
757 | |
758 | if (NO_ERROR != ret) { |
759 | LOGE("[%s:%d] Failed to set AudioTrack parameters. status=%d\n", |
760 | __FUNCTION__, __LINE__, ret); |
761 | goto err_exit; |
762 | } |
763 | |
764 | ret = mlpTracker->initCheck(); |
765 | if (NO_ERROR != ret) { |
766 | LOGE("[%s:%d] Failed to init AudioTrack. status=%d\n", __FUNCTION__, |
767 | __LINE__, ret); |
768 | goto err_exit; |
769 | } |
770 | |
771 | mlpTracker->start(); |
772 | ResetPointer(); |
773 | |
774 | #if debug == 1 |
775 | uint32_t frame_count; |
776 | frame_count = mlpTracker->frameCount(); |
777 | LOGE("~~~~~~[%s:%d] frame_count = %u\n", __FUNCTION__, __LINE__, frame_count); |
778 | #endif |
779 | |
780 | return 0; |
781 | |
782 | err_exit: // |
783 | DeleteAudioTracker(); |
784 | |
785 | return -1; |
786 | } |
787 | |
788 | int CAndroidAudio::initAudioRecorder(int sr) |
789 | { |
790 | status_t ret; |
791 | |
792 | if (NULL != mlpRecorder) { |
793 | LOGE("[%s:%d] Trying to new AudioRecord while it's still not NULL.\n", |
794 | __FUNCTION__, __LINE__); |
795 | goto err_exit; |
796 | } |
797 | |
798 | #if ANDROID_PLATFORM_SDK_VERSION < 19 |
799 | mlpRecorder = new AudioRecord(); |
800 | if (NULL == mlpRecorder) { |
801 | LOGE("[%s:%d] Failed to new AudioRecord.\n", __FUNCTION__, __LINE__); |
802 | goto err_exit; |
803 | } |
804 | #else |
805 | mmpAudioRecorder = new AudioRecord(); |
806 | mlpRecorder = mmpAudioRecorder.get(); |
807 | #endif |
808 | |
809 | ret = mlpRecorder->set(AUDIO_SOURCE_DEFAULT, //inputSource |
810 | sr, //sampleRate |
811 | AUDIO_FORMAT_PCM_16_BIT, //format |
812 | AUDIO_CHANNEL_IN_STEREO, //channelMask |
813 | 0, //frameCount |
814 | recorderCallback, //callback_t |
815 | NULL, //void* user |
816 | 0, //notificationFrames, |
817 | false, //threadCanCallJava |
818 | 0 //sessionId |
819 | ); |
820 | |
821 | if (NO_ERROR != ret) { |
822 | LOGE("[%s:%d] Failed to set AudioRecord parameters. status=%d\n", |
823 | __FUNCTION__, __LINE__, ret); |
824 | goto err_exit; |
825 | } |
826 | |
827 | ret = mlpRecorder->initCheck(); |
828 | if (NO_ERROR != ret) { |
829 | LOGE("[%s:%d] Failed to init AudioRecord. status=%d\n", __FUNCTION__, |
830 | __LINE__, ret); |
831 | goto err_exit; |
832 | } |
833 | |
834 | ret = mlpRecorder->start(); |
835 | if (NO_ERROR != ret) { |
836 | LOGE("[%s:%d] Failed to start AudioRecord. status=%d\n", __FUNCTION__, |
837 | __LINE__, ret); |
838 | goto err_exit; |
839 | } |
840 | #if debug == 1 |
841 | uint32_t frame_count; |
842 | frame_count = mlpRecorder->frameCount(); |
843 | LOGE("~~~~~~[%s:%d] frame_count = %u\n", __FUNCTION__, __LINE__, frame_count); |
844 | #endif |
845 | |
846 | return 0; |
847 | err_exit: // |
848 | DeleteAudioRecorder(); |
849 | return -1; |
850 | } |
851 | |
852 | int CAndroidAudio::amAndroidInit(int tm_sleep, int init_flag, int recordSr, int trackSr, |
853 | bool enable_noise_gate) |
854 | { |
855 | int tmp_ret; |
856 | LOGD("Enter amAndroidInit function.\n"); |
857 | |
858 | amAndroidUninit(0); |
859 | |
860 | // Init the noise gate filter |
861 | gUserSetEnableNoiseGate = enable_noise_gate; |
862 | if (enable_noise_gate && (gNoiseGateThresh > 0) |
863 | && GetAudioNoiseGateEnableCFG()) { |
864 | gEnableNoiseGate = true; |
865 | noise_filter_init(); |
866 | } else { |
867 | gEnableNoiseGate = false; |
868 | } |
869 | LOGE("[%s:%d] noise gate enabled:%d!\n", __FUNCTION__, __LINE__, |
870 | gEnableNoiseGate); |
871 | |
872 | if (InitTempBuffer() != 0) { |
873 | LOGE("[%s:%d] Failed to create temp_buffer!\n", __FUNCTION__, __LINE__); |
874 | return 0; |
875 | } |
876 | |
877 | if (init_flag & CC_FLAG_CREATE_RECORD) { |
878 | //LOGD("Start to create Recorder. RecordSr:%d\n", recordSr); |
879 | if (0 != initAudioRecorder(recordSr)) { |
880 | LOGE(" [%s:%d] Created AudioRecorder disable !\n", __FUNCTION__, |
881 | __LINE__); |
882 | return -1; |
883 | } |
884 | //LOGD("[%s:%d] End to create recorder.\n", __FUNCTION__, __LINE__); |
885 | } |
886 | |
887 | if (init_flag & CC_FLAG_CREATE_TRACK) { |
888 | //LOGD("Start to create Tracker. TrackSr:%d\n", trackSr); |
889 | if (0 != initAudioTracker(trackSr)) { |
890 | //FreeAudioRecorder(); |
891 | //FreeAudioTracker(); |
892 | LOGE(" [%s:%d] Created AudioTrack disable !\n", __FUNCTION__, |
893 | __LINE__); |
894 | return -1; |
895 | } |
896 | //LOGD("[%s:%d] End to create recorder.\n", __FUNCTION__, __LINE__); |
897 | } |
898 | |
899 | if (tm_sleep > 0) |
900 | sleep(tm_sleep); |
901 | |
902 | LOGD("Exit amAndroidInit function sucess.\n"); |
903 | |
904 | return 0; |
905 | } |
906 | |
907 | int CAndroidAudio::amAndroidUninit(int tm_sleep) |
908 | { |
909 | LOGD("Enter amAndroidUninit function.\n"); |
910 | |
911 | FreeAudioRecorder(); |
912 | // MuteTempBuffer(); |
913 | FreeAudioTracker(); |
914 | FreeTempBuffer(); |
915 | |
916 | if (tm_sleep > 0) |
917 | sleep(tm_sleep); |
918 | |
919 | LOGD("Exit amAndroidUninit function sucess.\n"); |
920 | |
921 | return 0; |
922 | } |
923 | |
924 | int CAndroidAudio::amAndroidSetRecorderSr(int sr) |
925 | { |
926 | int ret; |
927 | FreeAudioRecorder(); |
928 | ResetRecordWritePointer(); |
929 | return initAudioRecorder(sr); |
930 | } |
931 | |
932 | int CAndroidAudio::amAndroidSetTrackerSr(int sr) |
933 | { |
934 | FreeAudioTracker(); |
935 | ResetPlaybackReadPointer(); |
936 | return initAudioTracker(sr); |
937 | } |
938 | |
939 | // |
940 | // Set the noise gate threshold. |
941 | // If it's set to 0, the noise gate filter is disabled. |
942 | // Theoretically, this variable should be protected by mutex. But this API |
943 | // is designed to be called once on system boot, or for debug purpose, and it's |
944 | // set only through this API. To improve the performance of the filters, we |
945 | // don't utilize any mutex here. |
946 | void CAndroidAudio::amAndroidSetNoiseGateThreshold(int thresh) |
947 | { |
948 | int upperBound = GetAudioNoiseGateUpperBoundCFG(); |
949 | int forcedThresh = GetAudioNoiseGateThresholdCFG(); |
950 | if (forcedThresh >= 0) { |
951 | LOGE("Force noise gate threshold from %d to %d\n", thresh, |
952 | forcedThresh); |
953 | thresh = forcedThresh; |
954 | } |
955 | |
956 | if ((thresh >= 0) && (thresh <= upperBound)) { |
957 | gNoiseGateThresh = thresh; |
958 | } else { |
959 | gNoiseGateThresh = 0; |
960 | } |
961 | |
962 | if (gUserSetEnableNoiseGate && (gNoiseGateThresh > 0) |
963 | && GetAudioNoiseGateEnableCFG()) { |
964 | gEnableNoiseGate = true; |
965 | } else { |
966 | gEnableNoiseGate = false; |
967 | } |
968 | LOGE( |
969 | "[%s:%d] thresh:%d, upperBound:%d, gNoiseGateThresh:%d, gEnableNoiseGate:%d\n", |
970 | __FUNCTION__, __LINE__, thresh, upperBound, gNoiseGateThresh, |
971 | gEnableNoiseGate); |
972 | } |
973 | |
974 | int CAndroidAudio::amAndroidSetDumpDataFlag(int tmp_flag) |
975 | { |
976 | mDumpDataFlag = tmp_flag; |
977 | return mDumpDataFlag; |
978 | } |
979 | |
980 | int CAndroidAudio::amAndroidGetDumpDataFlag() |
981 | { |
982 | return mDumpDataFlag; |
983 | } |
984 | |
985 | void CAndroidAudio::DoDumpData(void *data_buf, int size) |
986 | { |
987 | int tmp_flag = 0; |
988 | char prop_value[PROPERTY_VALUE_MAX]; |
989 | |
990 | if (amAndroidGetDumpDataFlag() == 0) { |
991 | return; |
992 | } |
993 | |
994 | memset(prop_value, '\0', PROPERTY_VALUE_MAX); |
995 | |
996 | property_get("audio.dumpdata.en", prop_value, "null"); |
997 | if (strcasecmp(prop_value, "null") == 0 |
998 | || strcasecmp(prop_value, "0") == 0) { |
999 | if (mDumpDataFd >= 0) { |
1000 | close(mDumpDataFd); |
1001 | mDumpDataFd = -1; |
1002 | } |
1003 | |
1004 | return; |
1005 | } |
1006 | |
1007 | memset(prop_value, '\0', PROPERTY_VALUE_MAX); |
1008 | |
1009 | property_get("audio.dumpdata.path", prop_value, "null"); |
1010 | if (strcasecmp(prop_value, "null") == 0) { |
1011 | return; |
1012 | } |
1013 | |
1014 | if (mDumpDataFd < 0) { |
1015 | if (access(prop_value, 0) == 0) { |
1016 | mDumpDataFd = open(prop_value, O_RDWR | O_SYNC); |
1017 | if (mDumpDataFd < 0) { |
1018 | LOGE("%s, Open device file \"%s\" error: %s.\n", __FUNCTION__, |
1019 | prop_value, strerror(errno)); |
1020 | return; |
1021 | } |
1022 | } else { |
1023 | mDumpDataFd = open(prop_value, O_WRONLY | O_CREAT | O_EXCL, |
1024 | S_IRUSR | S_IWUSR); |
1025 | if (mDumpDataFd < 0) { |
1026 | LOGE("%s, Create device file \"%s\" error: %s.\n", __FUNCTION__, |
1027 | prop_value, strerror(errno)); |
1028 | return; |
1029 | } |
1030 | } |
1031 | } |
1032 | |
1033 | write(mDumpDataFd, data_buf, size); |
1034 | } |
1035 | |
1036 |