-rw-r--r-- | audio_hw.c | 204 | ||||
-rw-r--r-- | audio_hw.h | 16 | ||||
-rw-r--r-- | audio_hw_profile.c | 67 | ||||
-rw-r--r-- | audio_hw_profile.h | 20 | ||||
-rw-r--r-- | audio_hw_utils.c | 157 | ||||
-rw-r--r-- | audio_hw_utils.h | 20 | ||||
-rw-r--r-- | audio_hwsync.c | 18 | ||||
-rw-r--r-- | audio_hwsync.h | 18 |
8 files changed, 406 insertions, 114 deletions
diff --git a/audio_hw_utils.c b/audio_hw_utils.c index 17febea..6eb4bd6 100644 --- a/audio_hw_utils.c +++ b/audio_hw_utils.c @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2010 Amlogic Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + #define LOG_TAG "audio_hw_utils" #define LOG_NDEBUG 0 @@ -24,6 +42,7 @@ #include "audio_hwsync.h" #include "audio_hw.h" +#include <audio_utils/primitives.h> #ifdef LOG_NDEBUG_FUNCTION #define LOGFUNC(...) ((void)0) @@ -164,3 +183,141 @@ int getprop_bool (const char *path) return 0; } +/* +convert audio formats to supported audio format +8 ch goes to 32 bit +2 ch can be 16 bit or 32 bit +@return input buffer used by alsa drivers to do the data write +*/ +void *convert_audio_sample_for_output(int input_frames, int input_format, int input_ch, void *input_buf, int *out_size) +{ + float lvol = 1.0; + int *out_buf = NULL; + short *p16 = (short*)input_buf; + int *p32 = (int*)input_buf; + int max_ch = input_ch; + int i; + //ALOGV("intput frame %d,input ch %d,buf ptr %p,vol %f\n", input_frames, input_ch, input_buf, lvol); + ALOG_ASSERT(input_buf); + if (input_ch > 2) + max_ch = 8; + //our HW need round the frames to 8 channels + out_buf = malloc(sizeof(int) * max_ch * input_frames); + if (out_buf == NULL) { + ALOGE("malloc buffer failed\n"); + return NULL; + } + switch (input_format) { + case AUDIO_FORMAT_PCM_16_BIT: + break; + case AUDIO_FORMAT_PCM_32_BIT: + break; + case AUDIO_FORMAT_PCM_8_24_BIT: + for (i = 0; i < input_frames * input_ch; i++) { + p32[i] = p32[i] << 8; + } + break; + case AUDIO_FORMAT_PCM_FLOAT: + memcpy_to_i16_from_float(out_buf, input_buf, input_frames * input_ch); + memcpy(input_buf, out_buf, sizeof(short)*input_frames * input_ch); + break; + } + //current all the data are in the input buffer + if (input_ch == 8) { + short *p16_temp; + int i, NumSamps; + int *p32_temp = out_buf; + float m_vol = lvol; + NumSamps = input_frames * input_ch; + //here to swap the channnl data here + //actual now:L,missing,R,RS,RRS,,LS,LRS,missing + //expect L,C,R,RS,RRS,LRS,LS,LFE (LFE comes from to center) + //actual audio data layout L,R,C,none/LFE,LRS,RRS,LS,RS + if (input_format == AUDIO_FORMAT_PCM_16_BIT) { + p16_temp = (short*)out_buf; + for (i = 0; i < NumSamps; i = i + 8) { + p16_temp[0 + i]/*L*/ = m_vol * p16[0 + i]; + p16_temp[1 + i]/*R*/ = m_vol * p16[1 + i]; + p16_temp[2 + i] /*LFE*/ = m_vol * p16[3 + i]; + p16_temp[3 + i] /*C*/ = m_vol * p16[2 + i]; + p16_temp[4 + i] /*LS*/ = m_vol * p16[6 + i]; + p16_temp[5 + i] /*RS*/ = m_vol * p16[7 + i]; + p16_temp[6 + i] /*LRS*/ = m_vol * p16[4 + i]; + p16_temp[7 + i]/*RRS*/ = m_vol * p16[5 + i]; + } + memcpy(p16, p16_temp, NumSamps * sizeof(short)); + for (i = 0; i < NumSamps; i++) { //suppose 16bit/8ch PCM + p32_temp[i] = p16[i] << 16; + } + } else { + p32_temp = out_buf; + for (i = 0; i < NumSamps; i = i + 8) { + p32_temp[0 + i]/*L*/ = m_vol * p32[0 + i]; + p32_temp[1 + i]/*R*/ = m_vol * p32[1 + i]; + p32_temp[2 + i] /*LFE*/ = m_vol * p32[3 + i]; + p32_temp[3 + i] /*C*/ = m_vol * p32[2 + i]; + p32_temp[4 + i] /*LS*/ = m_vol * p32[6 + i]; + p32_temp[5 + i] /*RS*/ = m_vol * p32[7 + i]; + p32_temp[6 + i] /*LRS*/ = m_vol * p32[4 + i]; + p32_temp[7 + i]/*RRS*/ = m_vol * p32[5 + i]; + } + + } + *out_size = NumSamps * sizeof(int); + + } else if (input_ch == 6) { + int j, NumSamps, real_samples; + short *p16_temp; + int *p32_temp = out_buf; + float m_vol = lvol; + NumSamps = input_frames * input_ch; + real_samples = NumSamps; + NumSamps = real_samples * 8 / 6; + //ALOGI("6ch to 8 ch real %d, to %d\n",real_samples,NumSamps); + if (input_format == AUDIO_FORMAT_PCM_16_BIT) { + p16_temp = (short*)out_buf; + for (i = 0; i < real_samples; i = i + 6) { + p16_temp[0 + i]/*L*/ = m_vol * p16[0 + i]; + p16_temp[1 + i]/*R*/ = m_vol * p16[1 + i]; + p16_temp[2 + i] /*LFE*/ = m_vol * p16[3 + i]; + p16_temp[3 + i] /*C*/ = m_vol * p16[2 + i]; + p16_temp[4 + i] /*LS*/ = m_vol * p16[4 + i]; + p16_temp[5 + i] /*RS*/ = m_vol * p16[5 + i]; + } + memcpy(p16, p16_temp, real_samples * sizeof(short)); + memset(p32_temp, 0, NumSamps * sizeof(int)); + for (i = 0, j = 0; j < NumSamps; i = i + 6, j = j + 8) { //suppose 16bit/8ch PCM + p32_temp[j + 0] = p16[i] << 16; + p32_temp[j + 1] = p16[i + 1] << 16; + p32_temp[j + 2] = p16[i + 2] << 16; + p32_temp[j + 3] = p16[i + 3] << 16; + p32_temp[j + 4] = p16[i + 4] << 16; + p32_temp[j + 5] = p16[i + 5] << 16; + } + } else { + p32_temp = out_buf; + memset(p32_temp, 0, NumSamps * sizeof(int)); + for (i = 0, j = 0; j < NumSamps; i = i + 6, j = j + 8) { //suppose 16bit/8ch PCM + p32_temp[j + 0] = m_vol * p32[i + 0]; + p32_temp[j + 1] = m_vol * p32[i + 1] ; + p32_temp[j + 2] = m_vol * p32[i + 2] ; + p32_temp[j + 3] = m_vol * p32[i + 3] ; + p32_temp[j + 4] = m_vol * p32[i + 4] ; + p32_temp[j + 5] = m_vol * p32[i + 5] ; + } + } + *out_size = NumSamps * sizeof(int); + } else { + //2ch with 24 bit/32/float audio + int *p32_temp = out_buf; + short *p16_temp = (short*)out_buf; + for (i = 0; i < input_frames; i++) { + p16_temp[2 * i + 0] = lvol * p16[2 * i + 0]; + p16_temp[2 * i + 1] = lvol * p16[2 * i + 1]; + } + *out_size = sizeof(short) * input_frames * input_ch; + } + return out_buf; + +} + |