|
|
@@ -7,7 +7,8 @@
|
|
|
#include <assert.h>
|
|
|
#include <speex/speex_resampler.h>
|
|
|
#include <time.h>
|
|
|
-
|
|
|
+#include <semaphore.h>
|
|
|
+#include <pthread.h>
|
|
|
|
|
|
#define MAX_DELAY 60
|
|
|
#define CLOCK_PERIOD 20
|
|
|
@@ -15,42 +16,6 @@
|
|
|
#define CAPTURE_AUDIO_CLOCK 44100
|
|
|
#define RESAMPLE_QUALITY 6
|
|
|
|
|
|
-
|
|
|
-static void From32To16Bit(void* input_data, int input_samples, void* output_data, int out_samples) {
|
|
|
- int i = 0;
|
|
|
- float f;
|
|
|
- for (i = 0; i < input_samples; i++) {
|
|
|
- float* pinput = (float*)input_data + i;
|
|
|
- uint16_t* poutput = (uint16_t*)output_data + i;
|
|
|
- //Dbg("[From32To16Bit]pinput :%f", *pinput);
|
|
|
- f = *pinput;
|
|
|
- f = f * 32768;
|
|
|
- if (f > 32767) f = 32767;
|
|
|
- if (f < -32768) f = -32768;
|
|
|
- //转为正数
|
|
|
- *poutput = f + 32768;
|
|
|
- //Dbg("[From32To16Bit]poutput :%u, i: %d", *poutput, i);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void From16ToFloat(void* input_data, int input_samples, void* output_data, int out_samples) {
|
|
|
- int i = 0;
|
|
|
- int input_value;
|
|
|
- for (i = 0; i < input_samples; i++) {
|
|
|
- uint16_t* pinput = (uint16_t*)input_data + i;
|
|
|
- float* poutput = (float*)output_data + i;
|
|
|
- //Dbg("[From16ToFloat]pinput :%u", *pinput);
|
|
|
- input_value = *pinput;
|
|
|
- //转为有符合数
|
|
|
- input_value = input_value - 32768;
|
|
|
- *poutput = ((float)input_value) / (float)32768;
|
|
|
- if (*poutput > 1) *poutput = 1;
|
|
|
- if (*poutput < -1) *poutput = -1;
|
|
|
- //Dbg("[From16ToFloat]poutput :%f, i: %d", *poutput, i);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
static int get_device_index(int indev, const char* key)
|
|
|
{
|
|
|
int i;
|
|
|
@@ -81,6 +46,7 @@ static int outStreamCallback(const void* input,
|
|
|
|
|
|
if (output) {
|
|
|
unsigned nsamples_req = frameCount;
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
|
|
|
char* float_output;
|
|
|
int float_samples;
|
|
|
@@ -88,15 +54,16 @@ static int outStreamCallback(const void* input,
|
|
|
spx_uint16_t high_outdata[512] = { 0 };
|
|
|
spx_uint32_t in_len = micspk->frame_samples;
|
|
|
spx_uint32_t out_len = micspk->capture_frame_samples;
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d delay_buf_get", __FUNCTION__,__LINE__);
|
|
|
delay_buf_get((delay_buf*)micspk->ply_dbuf, data);
|
|
|
//if (micspk->pcmfile && strlen(data) > 0)
|
|
|
//{
|
|
|
// fwrite(data, in_len * sizeof(spx_int16_t), 1, micspk->pcmfile);
|
|
|
//}
|
|
|
- //if (micspk->user_data)
|
|
|
- //{
|
|
|
- // micspk->on_rx_audio((char*)data, micspk->user_data);
|
|
|
- //}
|
|
|
+ if (micspk->user_data)
|
|
|
+ {
|
|
|
+ micspk->on_rx_audio((char*)data, micspk->user_data);
|
|
|
+ }
|
|
|
speex_resampler_process_int((SpeexResamplerState*)micspk->output_resample_state, 0,
|
|
|
data, &in_len, (spx_int16_t*)output, &out_len);
|
|
|
//if (micspk->highhzpcmFile)
|
|
|
@@ -120,18 +87,14 @@ static int inStreamCallback(const void* input,
|
|
|
void* userData)
|
|
|
{
|
|
|
audiomicspklinux_t* micspk = userData;
|
|
|
- apr_status_t status;
|
|
|
|
|
|
if (input) {
|
|
|
int in_samples = frameCount; //采集为32位float
|
|
|
if (micspk->rec_buf_cnt == 0 && frameCount == micspk->frame_samples) {
|
|
|
- int before_resample_samples = frameCount;//重采样前转为16位
|
|
|
int after_resample_samples = frameCount;
|
|
|
- char before_resample_buffer[frameCount * 16 / 8];
|
|
|
- char after_resample_buffer[frameCount * 16 / 8];
|
|
|
- From32To16Bit(input, in_samples, before_resample_buffer, before_resample_samples);
|
|
|
+ spx_uint16_t after_resample_buffer[128] = {0};
|
|
|
speex_resampler_process_int((SpeexResamplerState*)micspk->input_resample_state, 0,
|
|
|
- before_resample_buffer, &before_resample_samples, (spx_int16_t*)after_resample_buffer, &after_resample_samples);
|
|
|
+ input, &in_samples, (spx_int16_t*)after_resample_buffer, &after_resample_samples);
|
|
|
delay_buf_put(micspk->rec_dbuf, (short*)after_resample_buffer);
|
|
|
}
|
|
|
else {
|
|
|
@@ -139,11 +102,9 @@ static int inStreamCallback(const void* input,
|
|
|
//先转换为需要的格式
|
|
|
int before_resample_samples = frameCount;//重采样前转为16位
|
|
|
int after_resample_samples = frameCount;
|
|
|
- char before_resample_buffer[frameCount * 16 / 8];
|
|
|
- char after_resample_buffer[frameCount * 16 / 8];
|
|
|
- From32To16Bit(input, in_samples, before_resample_buffer, before_resample_samples);
|
|
|
+ spx_int16_t after_resample_buffer[128] = {0};
|
|
|
speex_resampler_process_int((SpeexResamplerState*)micspk->input_resample_state, 0,
|
|
|
- before_resample_buffer, &before_resample_samples, (spx_int16_t*)after_resample_buffer, &after_resample_samples);
|
|
|
+ input, &before_resample_samples, (spx_int16_t*)after_resample_buffer, &after_resample_samples);
|
|
|
|
|
|
nsamples = after_resample_samples + micspk->rec_buf_cnt;
|
|
|
while (nsamples >= micspk->frame_samples) {
|
|
|
@@ -159,7 +120,7 @@ static int inStreamCallback(const void* input,
|
|
|
micspk->rec_buf_cnt += nsamples;
|
|
|
}
|
|
|
}
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micro inStreamCallback.");
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio micro inStreamCallback.");
|
|
|
}
|
|
|
|
|
|
return paContinue;
|
|
|
@@ -185,7 +146,7 @@ static apr_status_t write_frame(void* self, const audioframe_t* frame)
|
|
|
//audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%s:%d micspk->frame_samples = %d, frame->size = %d.", __FILE__, __FUNCTION__, __LINE__, micspk->frame_samples, frame->size);
|
|
|
assert(micspk->frame_samples * 2 == frame->size);
|
|
|
|
|
|
- //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%s:%d", __FILE__, __FUNCTION__, __LINE__);
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d delay_buf_put", __FUNCTION__, __LINE__);
|
|
|
delay_buf_put(micspk->ply_dbuf, (short*)frame->buffer);
|
|
|
//if (micspk->putpcmfile && strlen(frame->buffer) > 0)
|
|
|
//{
|
|
|
@@ -363,13 +324,18 @@ static void uninitialize_micro(audiomicspklinux_t* micspk)
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "uninitialize_micro success!");
|
|
|
}
|
|
|
|
|
|
-void* APR_THREAD_FUNC* audiowork_proc(apr_thread_t* threadhandle, void* param)
|
|
|
+//void* APR_THREAD_FUNC* audiowork_proc(apr_thread_t* threadhandle, void* param)
|
|
|
+void* audiowork_proc(void* param)
|
|
|
{
|
|
|
audiomicspklinux_t* micspk = (audiomicspklinux_t*)param;
|
|
|
int rc;
|
|
|
+ struct sched_param schparam;
|
|
|
+ int policy;
|
|
|
+
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x. started flag is %s.", __FUNCTION__, __LINE__, param, micspk->audio_device_started_sem, micspk->baudio_device_started_flag ? "true" : "false");
|
|
|
|
|
|
-
|
|
|
+ pthread_getschedparam(pthread_self(), &policy, &schparam);
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d current thread policy is %d, priority is %d.", __FUNCTION__, __LINE__, policy, schparam.sched_priority);
|
|
|
//
|
|
|
// record need play because of AEC, so
|
|
|
// record <---> record and play
|
|
|
@@ -465,6 +431,9 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
|
|
|
unsigned long frame_samples;
|
|
|
unsigned long capture_frame_samples;
|
|
|
|
|
|
+ pthread_attr_t attr;
|
|
|
+ struct sched_param param;
|
|
|
+
|
|
|
ply_dev_id = get_device_index(0, ply_dev_key);
|
|
|
rec_dev_id = get_device_index(1, rec_dev_key);
|
|
|
|
|
|
@@ -528,20 +497,34 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
|
|
|
micspk->baudio_device_started_flag = false;
|
|
|
sem_init(micspk->audio_device_started_sem, 0, 0);
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d micspk addr is 0x%0x, current sem addr is 0x%0x. started flag is %s.", __FUNCTION__, __LINE__, micspk, micspk->audio_device_started_sem, micspk->baudio_device_started_flag ? "true" : "false");
|
|
|
- apr_status_t err = apr_thread_create(&micspk->audio_work_threadid, NULL, audiowork_proc, micspk, pool);
|
|
|
- if (APR_SUCCESS == err) {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audiomicspk work thread success, %lu.", micspk->audio_work_threadid);
|
|
|
+
|
|
|
+ pthread_attr_init(&attr);
|
|
|
+ param.sched_priority = sched_get_priority_max(SCHED_RR);
|
|
|
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
|
|
+ pthread_attr_setschedparam(&attr, ¶m);
|
|
|
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
|
|
|
+ int err = pthread_create(&micspk->audio_work_threadid, &attr, audiowork_proc, micspk);
|
|
|
+ if (0 == err) {
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audio micspk work thread success, %lu.", micspk->audio_work_threadid);
|
|
|
+ //}
|
|
|
+ //else {
|
|
|
+ // audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audio micspk work thread failed.");
|
|
|
+ //}
|
|
|
+ //
|
|
|
+ //apr_status_t err = apr_thread_create(&micspk->audio_work_threadid, NULL, audiowork_proc, micspk, pool);
|
|
|
+ //if (APR_SUCCESS == err) {
|
|
|
+ // audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audiomicspk work thread success, %lu.", micspk->audio_work_threadid);
|
|
|
bool baudio_work_thread_exit = false;
|
|
|
|
|
|
do {
|
|
|
struct timespec ts;
|
|
|
- int ivalue = -1;
|
|
|
+ //int ivalue = -1;
|
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
long unsec = ts.tv_nsec + (1000 * 1000 * 10);
|
|
|
ts.tv_sec += (unsec / 1000000000);
|
|
|
ts.tv_nsec = (unsec % 1000000000);
|
|
|
- sem_getvalue(micspk->audio_device_started_sem, &ivalue);
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d current sem value is %d.", __FUNCTION__, __LINE__, ivalue);
|
|
|
+ //sem_getvalue(micspk->audio_device_started_sem, &ivalue);
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d current sem value is %d.", __FUNCTION__, __LINE__, ivalue);
|
|
|
if(-1 == sem_timedwait(micspk->audio_device_started_sem, &ts)) {
|
|
|
if (ETIMEDOUT == errno){
|
|
|
if (micspk->baudio_device_started_flag) {
|
|
|
@@ -557,14 +540,14 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
|
|
|
} while (!baudio_work_thread_exit);
|
|
|
|
|
|
if (baudio_work_thread_exit) {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
audiomicspklinux_destroy(micspk);
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
+ //audio_log_v(AUDIO_LOG_LEVEL_INFO, "%s:%d", __FUNCTION__, __LINE__);
|
|
|
return APR_EGENERAL;
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audiomicspk work thread failed.");
|
|
|
+ audio_log_v(AUDIO_LOG_LEVEL_INFO, "create audio micspk work thread failed.");
|
|
|
audiomicspklinux_destroy(micspk);
|
|
|
return APR_EGENERAL;
|
|
|
}
|