android13/hardware/rockchip/audio/tinyalsa_hal/voice_preprocess.c

687 lines
27 KiB
C

/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
/**
* @file voice_preprocess.c
* @author Sun Mingjun <smj@rock-chips.com>
* @date 2017-05-08
*/
//#define LOG_NDEBUG 0
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/time.h>
#include <dlfcn.h> // for dlopen/dlclose
#include <fcntl.h>
#include <string.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/str_parms.h>
//#include <speex/speex.h>
#include <speex/speex_preprocess.h>
#include <speex/speex_resampler.h>
#include "voice_preprocess.h"
#define LOG_TAG "voice_process"
#define MAX_BUFFER_SIZE (500 * 1024)
#define PROCESS_BUFFER_SIZE (256)
#define FILE_PATH "/etc/RK_VoicePara.bin"
#define false (0)
#define true (1)
#define bool int
//#define ALSA_3A_DEBUG
#ifdef ALSA_3A_DEBUG
FILE *in_capture_debug;
FILE *out_capture_debug;
FILE *in_playback_debug;
FILE *out_playback_debug;
#endif
typedef struct voiceThread_t_ {
bool running;
pthread_t thread;
sem_t sem;
int threadStatus;
pthread_mutex_t queueCapLock;
pthread_mutex_t queuePlyLock;
pthread_mutex_t getCapOutLock;
pthread_mutex_t getPlyOutLock;
} voiceThread_t;
typedef struct rk_voice_api_ {
int (*init)(char *para);
void (*processCapture)(short *in, short *ref, short *out, int len);
void (*processPlayback)(short *in, short *out, int len);
void (*deinit)();
} rk_voice_api;
typedef struct rk_voice_handle_ {
void* voiceLibHandle;
rk_voice_api *voiceApi;
rk_process_api *processApi;
char* playBackBuffer;
char* captureBuffer;
char* outPlayBuffer;
char* outCaptureBuffer;
SpeexResamplerState* speexCapureDownResample;
SpeexResamplerState* speexCapureUpResample;
SpeexResamplerState* speexPlaybackDownResample;
SpeexResamplerState* speexPlaybackUpResample;
voiceThread_t voice_thread;
int playbackBufferSize;
int captureBufferSize;
int outPlaybackBufferSize;
int outCaptureBufferSize;
int captureInSamplerate;
int processSamplerate;
int playbackInSamplerate;
int captureInChannels;
int processChannels;
int playbackInChannels;
int processBuffersize;
int minPlaybackBuffersize;
int minCaptureBuffersize;
} rk_voice_handle;
static rk_voice_handle *voice_handle = NULL;
static int prop_pcm_record = 0;
static void thread_loop(rk_voice_handle* handle);
static void* thread_start(void* argv);
static void dump_out_data(const void* buffer,size_t bytes, int *size)
{
static FILE* fd = NULL;
static int offset = 0;
if(fd == NULL) {
fd=fopen("/data/1.pcm","wb+");
if(fd == NULL) {
ALOGD("DEBUG open error =%d ,errno = %d",fd,errno);
offset = 0;
}
}
fwrite(buffer,bytes,1,fd);
offset += bytes;
fflush(fd);
if(offset >= (*size)*1024*1024) {
*size = 0;
fclose(fd);
offset = 0;
}
}
static inline rk_voice_handle* getHandle()
{
return voice_handle;
}
static int start()
{
rk_voice_handle* voiceHandle = getHandle();
sem_init(&voice_handle->voice_thread.sem, 0, 1);
voiceHandle->voice_thread.running = true;
if (voiceHandle->voice_thread.threadStatus == -1)
voiceHandle->voice_thread.threadStatus = pthread_create(&voiceHandle->voice_thread.thread, NULL, thread_start, voiceHandle);
ALOGD("voice process start !, ret = %d", voiceHandle->voice_thread.threadStatus);
return 0;
}
static int queueCaputureBuffer(void *buf, int size)
{
rk_voice_handle* voiceHandle = getHandle();
if (voiceHandle->playbackBufferSize <= 0) {
ALOGV("not queue capture buffer until playback buffer queued");
return -1;
}
pthread_mutex_lock(&voiceHandle->voice_thread.queueCapLock);
if (voiceHandle->captureBufferSize + size >= MAX_BUFFER_SIZE) {
ALOGW("capture buffer size out of range, flush");
memset(voiceHandle->captureBuffer, 0x00, MAX_BUFFER_SIZE);
voiceHandle->captureBufferSize = 0;
}
memcpy((char *)voiceHandle->captureBuffer + voiceHandle->captureBufferSize, (char *)buf, size);
voiceHandle->captureBufferSize += size;
pthread_mutex_unlock(&voiceHandle->voice_thread.queueCapLock);
if ((voiceHandle->captureBufferSize >= voiceHandle->minCaptureBuffersize)
&& (voiceHandle->playbackBufferSize >= voiceHandle->minPlaybackBuffersize)) {
sem_post(&voiceHandle->voice_thread.sem);
}
return 0;
}
static int queuePlaybackBuffer(void *buf, int size)
{
rk_voice_handle* voiceHandle = getHandle();
pthread_mutex_lock(&voiceHandle->voice_thread.queuePlyLock);
if (voiceHandle->playbackBufferSize + size >= MAX_BUFFER_SIZE) {
ALOGW("capture buffer size out of range, flush");
memset(voiceHandle->playBackBuffer, 0x00, MAX_BUFFER_SIZE);
voiceHandle->playbackBufferSize = 0;
}
memcpy((char *)voiceHandle->playBackBuffer+ voiceHandle->playbackBufferSize, (char *)buf, size);
voiceHandle->playbackBufferSize+= size;
pthread_mutex_unlock(&voiceHandle->voice_thread.queuePlyLock);
if ((voiceHandle->captureBufferSize >= voiceHandle->minCaptureBuffersize)
&& (voiceHandle->playbackBufferSize >= voiceHandle->minPlaybackBuffersize)) {
sem_post(&voiceHandle->voice_thread.sem);
}
return 0;
}
static int getCapureBuffer(void *buf, int size)
{
rk_voice_handle* voiceHandle = getHandle();
if (voiceHandle->outCaptureBufferSize < size) {
ALOGW("cannot get caputre buffer currently, try next time");
return -1;
}
pthread_mutex_lock(&voiceHandle->voice_thread.getCapOutLock);
memcpy((char *)buf, voiceHandle->outCaptureBuffer, size);
memcpy(voiceHandle->outCaptureBuffer, voiceHandle->outCaptureBuffer+size, MAX_BUFFER_SIZE-size);
voiceHandle->outCaptureBufferSize -= size;
pthread_mutex_unlock(&voiceHandle->voice_thread.getCapOutLock);
return 0;
}
static int getPlaybackBuffer(void *buf, int size)
{
rk_voice_handle* voiceHandle = getHandle();
if (voiceHandle->outPlaybackBufferSize < size) {
ALOGW("cannot get playback buffer currently, try next time");
return -1;
}
pthread_mutex_lock(&voiceHandle->voice_thread.getPlyOutLock);
memcpy((char *)buf, (char *)voiceHandle->outPlayBuffer, size);
memcpy((char *)voiceHandle->outPlayBuffer, (char *)voiceHandle->outPlayBuffer+size, MAX_BUFFER_SIZE-size);
voiceHandle->outPlaybackBufferSize -= size;
pthread_mutex_unlock(&voiceHandle->voice_thread.getPlyOutLock);
return 0;
}
static int flush()
{
rk_voice_handle* voiceHandle = getHandle();
pthread_mutex_lock(&voiceHandle->voice_thread.queuePlyLock);
memset((char *)voiceHandle->playBackBuffer, 0x00, MAX_BUFFER_SIZE);
voiceHandle->playbackBufferSize = 0;
pthread_mutex_unlock(&voiceHandle->voice_thread.queuePlyLock);
pthread_mutex_lock(&voiceHandle->voice_thread.queueCapLock);
memset((char *)voiceHandle->captureBuffer, 0x00, MAX_BUFFER_SIZE);
voiceHandle->captureBufferSize = 0;
pthread_mutex_unlock(&voiceHandle->voice_thread.queueCapLock);
return 0;
}
rk_process_api* rk_voiceprocess_create(int ply_sr, int ply_ch, int cap_sr, int cap_ch)
{
if (voice_handle != NULL) {
ALOGW(" voice handle has already opened, return");
return voice_handle->processApi;
}
voice_handle = (rk_voice_handle *)malloc(sizeof(rk_voice_handle));
if (voice_handle== NULL) {
ALOGE("voice Handle malloc failed!");
goto failed;
}
voice_handle->voiceLibHandle = NULL;
voice_handle->voiceApi = NULL;
voice_handle->processApi = NULL;
voice_handle->playBackBuffer = NULL;
voice_handle->captureBuffer = NULL;
voice_handle->speexCapureDownResample = NULL;
voice_handle->speexCapureUpResample = NULL;
voice_handle->speexPlaybackDownResample = NULL;
voice_handle->speexPlaybackUpResample = NULL;
voice_handle->playbackBufferSize = 0;
voice_handle->captureBufferSize = 0;
voice_handle->outPlaybackBufferSize = 0;
voice_handle->outCaptureBufferSize = 0;
voice_handle->captureInSamplerate = cap_sr;
voice_handle->processSamplerate = 16000;
voice_handle->playbackInSamplerate = ply_sr;
voice_handle->captureInChannels = cap_ch;
voice_handle->processChannels = 1;
voice_handle->playbackInChannels = ply_ch;
voice_handle->minPlaybackBuffersize = PROCESS_BUFFER_SIZE * 2 * voice_handle->playbackInSamplerate / voice_handle->processSamplerate * voice_handle->playbackInChannels;
voice_handle->minCaptureBuffersize = PROCESS_BUFFER_SIZE * 2 * voice_handle->captureInSamplerate / voice_handle->processSamplerate * voice_handle->captureInChannels;
voice_handle->voice_thread.running = false;
voice_handle->voice_thread.threadStatus = -1;
// open the voice process lib
voice_handle->voiceLibHandle = dlopen("/system/lib/libvoiceprocess.so", RTLD_LAZY);
if (voice_handle->voiceLibHandle == NULL) {
ALOGW("dlopen libvoiceprocess lib error!");
goto failed;
}
voice_handle->voiceApi = (rk_voice_api *)malloc(sizeof(rk_voice_api));
if (voice_handle->voiceApi == NULL) {
ALOGE("voiceApi malloc error! return");
goto failed;
}
memset(voice_handle->voiceApi, 0, sizeof(rk_voice_api));
voice_handle->voiceApi->init = (int (*)(char *))dlsym(voice_handle->voiceLibHandle,
"RK_VOICE_Init");
voice_handle->voiceApi->processCapture = (void (*)(short *in,
short *ref, short *out,
int len))dlsym(voice_handle->voiceLibHandle,
"RK_VOICE_ProcessTx");
voice_handle->voiceApi->processPlayback = (void (*)(short *in,
short *out,
int len))dlsym(voice_handle->voiceLibHandle,
"RK_VOICE_ProcessRx");
voice_handle->voiceApi->deinit= (void (*)())dlsym(voice_handle->voiceLibHandle,
"RK_VOICE_Destory");
if ((voice_handle->voiceApi->init == NULL)
|| (voice_handle->voiceApi->processCapture == NULL)
|| (voice_handle->voiceApi->processPlayback == NULL)
|| (voice_handle->voiceApi->deinit == NULL)) {
ALOGE("dlsym voice process lib failed, return");
goto failed;
}
// init the voice process lib
int ret = 0;
ret = voice_handle->voiceApi->init(FILE_PATH);
ALOGD("voice api init ret = %d", ret);
if (ret != 0) {
ALOGE("init %s failed", FILE_PATH);
}
// init the processApi interface
voice_handle->processApi = (rk_process_api *)malloc(sizeof(rk_process_api));
voice_handle->processApi->start = start;
voice_handle->processApi->getCapureBuffer = getCapureBuffer;
voice_handle->processApi->getPlaybackBuffer = getPlaybackBuffer;
voice_handle->processApi->queuePlaybackBuffer = queuePlaybackBuffer;
voice_handle->processApi->quueCaputureBuffer = queueCaputureBuffer;
voice_handle->processApi->flush = flush;
// malloc process buffers
voice_handle->playBackBuffer = (char *)malloc(MAX_BUFFER_SIZE);
voice_handle->captureBuffer = (char *)malloc(MAX_BUFFER_SIZE);
voice_handle->outPlayBuffer = (char *)malloc(MAX_BUFFER_SIZE);
voice_handle->outCaptureBuffer = (char *)malloc(MAX_BUFFER_SIZE);
if ((voice_handle->playBackBuffer == NULL) || (voice_handle->captureBuffer == NULL)
||(voice_handle->outPlayBuffer == NULL) || (voice_handle->outCaptureBuffer == NULL)) {
ALOGE("malloc playback or capure buffer falied!");
goto failed;
}
pthread_mutex_init(&voice_handle->voice_thread.queuePlyLock, NULL);
pthread_mutex_init(&voice_handle->voice_thread.queueCapLock, NULL);
pthread_mutex_init(&voice_handle->voice_thread.getCapOutLock, NULL);
pthread_mutex_init(&voice_handle->voice_thread.getPlyOutLock, NULL);
if (voice_handle->captureInSamplerate != voice_handle->processSamplerate) {
voice_handle->speexCapureDownResample = speex_resampler_init(1, voice_handle->captureInSamplerate, voice_handle->processSamplerate, SPEEX_RESAMPLER_QUALITY_DESKTOP, NULL);
voice_handle->speexCapureUpResample = speex_resampler_init(1, voice_handle->processSamplerate, voice_handle->captureInSamplerate, SPEEX_RESAMPLER_QUALITY_DESKTOP, NULL);
}
if (voice_handle->playbackInSamplerate!= voice_handle->processSamplerate) {
voice_handle->speexPlaybackDownResample = speex_resampler_init(1, voice_handle->playbackInSamplerate, voice_handle->processSamplerate, SPEEX_RESAMPLER_QUALITY_DESKTOP, NULL);
voice_handle->speexPlaybackUpResample = speex_resampler_init(1, voice_handle->processSamplerate, voice_handle->playbackInSamplerate, SPEEX_RESAMPLER_QUALITY_DESKTOP, NULL);
}
ALOGD("voice proceess handle create success!");
return voice_handle->processApi;
failed :
rk_voiceprocess_destory();
ALOGD("voice process handle create failed");
return NULL;
}
int rk_voiceprocess_destory()
{
ALOGD("voiceprocess_destory");
if (voice_handle == NULL) {
ALOGD("voiceprocess_destory return");
return 0;
}
if (voice_handle->voice_thread.threadStatus >= 0) {
voice_handle->voice_thread.running = false;
sem_post(&voice_handle->voice_thread.sem);
ALOGD("join thread in");
pthread_join(voice_handle->voice_thread.thread, NULL);
voice_handle->voice_thread.threadStatus = -1;
ALOGD("join thread out");
sem_destroy(&voice_handle->voice_thread.sem);
}
if (voice_handle->speexCapureDownResample) {
speex_resampler_destroy(voice_handle->speexCapureDownResample);
voice_handle->speexCapureDownResample = NULL;
}
if (voice_handle->speexCapureDownResample) {
speex_resampler_destroy(voice_handle->speexCapureDownResample);
voice_handle->speexCapureDownResample = NULL;
}
if (voice_handle->speexPlaybackUpResample) {
speex_resampler_destroy(voice_handle->speexPlaybackUpResample);
voice_handle->speexPlaybackUpResample = NULL;
}
if (voice_handle->speexPlaybackDownResample) {
speex_resampler_destroy(voice_handle->speexPlaybackDownResample);
voice_handle->speexPlaybackDownResample = NULL;
}
if (voice_handle->playBackBuffer != NULL) {
pthread_mutex_lock(&voice_handle->voice_thread.queuePlyLock);
free(voice_handle->playBackBuffer);
voice_handle->playBackBuffer = NULL;
voice_handle->playbackBufferSize = 0;
pthread_mutex_unlock(&voice_handle->voice_thread.queuePlyLock);
}
if (voice_handle->captureBuffer != NULL) {
pthread_mutex_lock(&voice_handle->voice_thread.queueCapLock);
free(voice_handle->captureBuffer);
voice_handle->captureBuffer = NULL;
voice_handle->captureBufferSize = 0;
pthread_mutex_unlock(&voice_handle->voice_thread.queueCapLock);
}
if (voice_handle->outPlayBuffer != NULL) {
pthread_mutex_lock(&voice_handle->voice_thread.getPlyOutLock);
free(voice_handle->outPlayBuffer);
voice_handle->outPlayBuffer = NULL;
voice_handle->outPlaybackBufferSize = 0;
pthread_mutex_unlock(&voice_handle->voice_thread.getPlyOutLock);
}
if (voice_handle->outCaptureBuffer != NULL) {
pthread_mutex_lock(&voice_handle->voice_thread.getCapOutLock);
free(voice_handle->outCaptureBuffer);
voice_handle->outCaptureBuffer = NULL;
voice_handle->outCaptureBufferSize = 0;
pthread_mutex_unlock(&voice_handle->voice_thread.getCapOutLock);
}
if (voice_handle->processApi) {
free(voice_handle->processApi);
voice_handle->processApi = NULL;
}
if (voice_handle->voiceApi) {
voice_handle->voiceApi->deinit();
}
if (voice_handle->voiceApi != NULL) {
free(voice_handle->voiceApi);
voice_handle->voiceApi = NULL;
}
if (voice_handle->voiceLibHandle != NULL) {
dlclose(voice_handle->voiceLibHandle);
voice_handle->voiceLibHandle = NULL;
}
if (voice_handle != NULL) {
free(voice_handle);
voice_handle = NULL;
}
ALOGD("voice process handle destory success!");
return 0;
}
static int processBuffertoMono(void *buffer, int size)
{
short *in = (short *)buffer;
short out[size/4];
int i = 0, j = 0;
for(i = 0, j = 0; i < size/4; i++) {
out[i] = (in[j] + in[j+1]) / 2;
j+=2;
}
memset((char *)in, 0x00, size);
memcpy((char *)in, (char *)out, size/2);
return 0;
}
static int processBuffertoStereo(void *buffer, int size)
{
short *in = (short *)buffer;
short out[size];
int i = 0,j = 0;;
for (i = 0, j = 0; i < size/2; i++) {
out[j] = in[i];
out[j+1] = in[i];
j+=2;
}
memcpy((char *)in, (char *)out, size * 2);
return 0;
}
static void thread_loop(rk_voice_handle* handle)
{
int playback_samplerate = handle->playbackInSamplerate;
int capture_samplerate = handle->captureInSamplerate;
int process_samplerate = handle->processSamplerate;
int playback_channel = handle->playbackInChannels;
int capture_channel = handle->captureInChannels;
int process_buffer_size = PROCESS_BUFFER_SIZE * 2;
int playback_min_buffersize = process_buffer_size * playback_samplerate / process_samplerate * playback_channel;
int capture_min_buffersize = process_buffer_size * capture_samplerate / process_samplerate * capture_channel;
char tmp_playback_buffer[playback_min_buffersize];
char tmp_capture_buffer[capture_min_buffersize];
char tmp_outplayback_buffer[playback_min_buffersize];
char tmp_outcapture_buffer[capture_min_buffersize];
#ifdef ALSA_3A_DEBUG
in_capture_debug = fopen("/data/3a_capture_in.pcm","wb");//please touch /data/3a_in.pcm first
out_capture_debug = fopen("/data/3a_capture_out.pcm","wb");//please touch /data/3a_out.pcm first
in_playback_debug = fopen("/data/3a_playback_in.pcm","wb");//please touch /data/3a_ref.pcm first
out_playback_debug = fopen("/data/3a_playback_out.pcm","wb");//please touch /data/3a_rx.pcm first
#endif
while (handle->voice_thread.running) {
bool isGetBuffer = false;
//wait the enough raw buffer
if ((handle->captureBufferSize < capture_min_buffersize) || (handle->playbackBufferSize < playback_min_buffersize)) {
sem_wait(&handle->voice_thread.sem);
}
char value[PROPERTY_VALUE_MAX] = "";
property_get("vendor.audio.record", value, NULL);
prop_pcm_record = atoi(value);
// try to get the raw buffer to process
if ((handle->captureBufferSize >= capture_min_buffersize) && (handle->playbackBufferSize >= playback_min_buffersize)) {
pthread_mutex_lock(&handle->voice_thread.queueCapLock);
memcpy(tmp_capture_buffer, handle->captureBuffer, capture_min_buffersize);
memcpy(handle->captureBuffer, handle->captureBuffer+capture_min_buffersize, MAX_BUFFER_SIZE-capture_min_buffersize);
handle->captureBufferSize -= capture_min_buffersize;
pthread_mutex_unlock(&handle->voice_thread.queueCapLock);
pthread_mutex_lock(&handle->voice_thread.queuePlyLock);
memcpy(tmp_playback_buffer, handle->playBackBuffer, playback_min_buffersize);
memcpy(handle->playBackBuffer, handle->playBackBuffer+playback_min_buffersize, MAX_BUFFER_SIZE-playback_min_buffersize);
handle->playbackBufferSize -= playback_min_buffersize;
pthread_mutex_unlock(&handle->voice_thread.queuePlyLock);
isGetBuffer = true;
}
// process the raw buffer and queue to output list
if (isGetBuffer) {
// process buffer to mono
if (playback_channel > 1) {
processBuffertoMono(tmp_playback_buffer, playback_min_buffersize);
}
if (capture_channel > 1) {
processBuffertoMono(tmp_capture_buffer, capture_min_buffersize);
}
// resample raw buffer to processed samplerate
if (playback_samplerate != process_samplerate) {
int in_sample = playback_min_buffersize / playback_channel / 2;
int out_sample = in_sample;
char tmp_resample_buffer[playback_min_buffersize];
memcpy(tmp_resample_buffer, tmp_playback_buffer, playback_min_buffersize);
memset(tmp_playback_buffer, 0x00, playback_min_buffersize);
speex_resampler_process_interleaved_int(handle->speexPlaybackDownResample,
(spx_int16_t *)tmp_resample_buffer, &in_sample,
(spx_int16_t *)tmp_playback_buffer, &out_sample);
ALOGV("playback down resample process, in_sample = %d, out_sample = %d", in_sample, out_sample);
}
if (capture_samplerate != process_samplerate) {
int in_sample = capture_min_buffersize / capture_channel / 2;
int out_sample = in_sample;
char tmp_resample_buffer[playback_min_buffersize];
memcpy(tmp_resample_buffer, tmp_capture_buffer, capture_min_buffersize);
memset(tmp_capture_buffer, 0x00, capture_min_buffersize);
speex_resampler_process_interleaved_int(handle->speexCapureDownResample,
(spx_int16_t *)tmp_resample_buffer, &in_sample,
(spx_int16_t *)tmp_capture_buffer, &out_sample);
ALOGV("capture down resample process, in_sample = %d, out_sample = %d,capture_samplerate = %d", in_sample, out_sample,capture_samplerate);
}
// main process call
if (handle->voiceApi) {
//memcpy((char *)tmp_outplayback_buffer, (char *)tmp_playback_buffer, PROCESS_BUFFER_SIZE * 2);
//memcpy((char *)tmp_outcapture_buffer, (char *)tmp_capture_buffer, PROCESS_BUFFER_SIZE * 2);
handle->voiceApi->processPlayback((short *)tmp_playback_buffer, (short *)tmp_outplayback_buffer, PROCESS_BUFFER_SIZE);
handle->voiceApi->processCapture((short *)tmp_capture_buffer, (short *)tmp_outplayback_buffer, (short *)tmp_outcapture_buffer, PROCESS_BUFFER_SIZE);
#ifdef ALSA_3A_DEBUG
fwrite(tmp_capture_buffer,sizeof(short),PROCESS_BUFFER_SIZE,in_capture_debug);
fwrite(tmp_outcapture_buffer,sizeof(short),PROCESS_BUFFER_SIZE,out_capture_debug);
fwrite(tmp_playback_buffer,sizeof(short),PROCESS_BUFFER_SIZE,in_playback_debug);
fwrite(tmp_outplayback_buffer,sizeof(short),PROCESS_BUFFER_SIZE,out_playback_debug);
#endif
}
// upresample the processed buffer to raw buffer samplerate
if (playback_samplerate != process_samplerate) {
int in_sample = PROCESS_BUFFER_SIZE;
int out_sample = playback_min_buffersize;
memset(tmp_playback_buffer, 0x00, playback_min_buffersize);
memcpy(tmp_playback_buffer, tmp_outplayback_buffer, process_buffer_size);
speex_resampler_process_interleaved_int(handle->speexPlaybackUpResample,
(spx_int16_t *)tmp_playback_buffer, &in_sample,
(spx_int16_t *)tmp_outplayback_buffer, &out_sample);
ALOGV("playback up resample process, in_sample = %d, out_sample = %d", in_sample, out_sample);
}
if (capture_samplerate != process_samplerate) {
int in_sample = PROCESS_BUFFER_SIZE;
int out_sample = capture_min_buffersize;
memset(tmp_capture_buffer, 0x00, capture_min_buffersize);
memcpy(tmp_capture_buffer, tmp_outcapture_buffer, process_buffer_size);
speex_resampler_process_interleaved_int(handle->speexCapureUpResample,
(spx_int16_t *)tmp_capture_buffer, &in_sample,
(spx_int16_t *)tmp_outcapture_buffer, &out_sample);
ALOGV("capture up resample process, in_sample = %d, out_sample = %d", in_sample, out_sample);
}
// up adjust channel to raw buffer channels
if (playback_channel > 1) {
processBuffertoStereo(tmp_outplayback_buffer, playback_min_buffersize/2);
}
if (capture_channel > 1) {
processBuffertoStereo(tmp_outcapture_buffer, capture_min_buffersize/2);
}
// queue processed buffer to output list
pthread_mutex_lock(&handle->voice_thread.getCapOutLock);
memcpy((char *)handle->outCaptureBuffer + handle->outCaptureBufferSize, tmp_outcapture_buffer, capture_min_buffersize);
handle->outCaptureBufferSize += capture_min_buffersize;
pthread_mutex_unlock(&handle->voice_thread.getCapOutLock);
pthread_mutex_lock(&handle->voice_thread.getPlyOutLock);
memcpy((char *)handle->outPlayBuffer + handle->outPlaybackBufferSize, tmp_outplayback_buffer, playback_min_buffersize);
handle->outPlaybackBufferSize += playback_min_buffersize;
pthread_mutex_unlock(&handle->voice_thread.getPlyOutLock);
}
}
#ifdef ALSA_3A_DEBUG
fclose(in_capture_debug);
fclose(out_capture_debug);
fclose(in_playback_debug);
fclose(out_playback_debug);
#endif
}
static void* thread_start(void* argv)
{
rk_voice_handle* handle = (rk_voice_handle*)argv;
thread_loop(handle);
return NULL;
}