|
|
@@ -11,6 +11,44 @@
|
|
|
|
|
|
#define MAX_DELAY 60
|
|
|
#define CLOCK_PERIOD 20
|
|
|
+#define AUDIO_CLOCK 8000
|
|
|
+#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)
|
|
|
{
|
|
|
@@ -41,20 +79,26 @@ static int outStreamCallback(const void* input,
|
|
|
apr_status_t status;
|
|
|
|
|
|
if (output) {
|
|
|
- //unsigned nsamples_req = frameCount;
|
|
|
- //if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
|
|
|
- // SHORT data[160];
|
|
|
- // spx_uint32_t in_len = micspk->frame_samples;
|
|
|
- // spx_uint32_t out_len = micspk->capture_frame_samples;
|
|
|
- // delay_buf_get((delay_buf*)micspk->ply_dbuf, 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);
|
|
|
- // memcpy(output, data, in_len*sizeof(float));
|
|
|
- //}
|
|
|
+ unsigned nsamples_req = frameCount;
|
|
|
+ if (micspk->ply_buf_cnt == 0 && nsamples_req == micspk->capture_frame_samples) {
|
|
|
+ char* float_output;
|
|
|
+ int float_samples;
|
|
|
+ SHORT data[160];
|
|
|
+ spx_uint32_t in_len = micspk->frame_samples;
|
|
|
+ spx_uint32_t out_len = micspk->capture_frame_samples;
|
|
|
+ delay_buf_get((delay_buf*)micspk->ply_dbuf, 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);
|
|
|
+ float_samples = out_len;
|
|
|
+ float_output = malloc(float_samples * 32 / 8);
|
|
|
+ From16ToFloat(output, out_len, float_output, float_samples);
|
|
|
+ memcpy(output, float_output, float_samples * 32 / 8);
|
|
|
+ free(float_output);
|
|
|
+ }
|
|
|
audio_log_v(AUDIO_LOG_LEVEL_INFO, "audio speaker outStreamCallback.");
|
|
|
}
|
|
|
return paContinue;
|
|
|
@@ -72,21 +116,39 @@ static int inStreamCallback(const void* input,
|
|
|
apr_status_t status;
|
|
|
|
|
|
if (input) {
|
|
|
+ int in_samples = frameCount; //采集为32位float
|
|
|
if (micspk->rec_buf_cnt == 0 && frameCount == micspk->frame_samples) {
|
|
|
- delay_buf_put(micspk->rec_dbuf, (short*)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);
|
|
|
+ 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);
|
|
|
+ delay_buf_put(micspk->rec_dbuf, (short*)after_resample_buffer);
|
|
|
}
|
|
|
else {
|
|
|
- unsigned long nsamples = frameCount + micspk->rec_buf_cnt;
|
|
|
+ unsigned long nsamples;
|
|
|
+ //先转换为需要的格式
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+
|
|
|
+ nsamples = after_resample_samples + micspk->rec_buf_cnt;
|
|
|
while (nsamples >= micspk->frame_samples) {
|
|
|
unsigned chunk_count = micspk->frame_samples - micspk->rec_buf_cnt;
|
|
|
- memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, chunk_count << 1);
|
|
|
- input = (const short*)input + chunk_count;
|
|
|
+ memcpy(micspk->rec_buf + micspk->rec_buf_cnt, after_resample_buffer, chunk_count << 1);
|
|
|
+ input = (const float*)input + chunk_count;
|
|
|
delay_buf_put(micspk->rec_dbuf, micspk->rec_buf);
|
|
|
micspk->rec_buf_cnt = 0;
|
|
|
nsamples -= micspk->frame_samples;
|
|
|
}
|
|
|
if (nsamples > 0) {
|
|
|
- memcpy(micspk->rec_buf + micspk->rec_buf_cnt, input, nsamples << 1);
|
|
|
+ memcpy(micspk->rec_buf + micspk->rec_buf_cnt, after_resample_buffer, nsamples << 1);
|
|
|
micspk->rec_buf_cnt += nsamples;
|
|
|
}
|
|
|
}
|
|
|
@@ -394,7 +456,7 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
|
|
|
micspk->audio_device_started_sem = (sem_t*)apr_palloc(pool, sizeof(sem_t));
|
|
|
|
|
|
frame_samples = FRAME_TIME * clock / 1000;
|
|
|
- capture_frame_samples = FRAME_TIME * clock / 1000;
|
|
|
+ capture_frame_samples = FRAME_TIME * CAPTURE_AUDIO_CLOCK / 1000;
|
|
|
|
|
|
micspk->rec_dev_id = rec_dev_id;
|
|
|
micspk->ply_dev_id = ply_dev_id;
|
|
|
@@ -411,14 +473,14 @@ apr_status_t audiomicspklinux_create(apr_pool_t* pool,
|
|
|
delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)& micspk->ply_dbuf);
|
|
|
micspk->ply_buf = (short*)apr_palloc(pool, frame_samples << 1);
|
|
|
micspk->ply_buf_cnt = 0;
|
|
|
- //micspk->output_resample_state = speex_resampler_init(1, AUDIO_CLOCK, CAPTURE_AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
|
|
|
+ micspk->output_resample_state = speex_resampler_init(1, AUDIO_CLOCK, CAPTURE_AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
|
|
|
}
|
|
|
if (opt & AMS_OPT_RECORD) {
|
|
|
micspk->base.direction |= STREAM_DIR_READ;
|
|
|
delay_buf_create(clock, frame_samples, 1, MAX_DELAY, 0, (delay_buf**)& micspk->rec_dbuf);
|
|
|
micspk->rec_buf = (short*)apr_palloc(pool, frame_samples << 1);
|
|
|
micspk->rec_buf_cnt = 0;
|
|
|
- //micspk->input_resample_state = speex_resampler_init(1, CAPTURE_AUDIO_CLOCK, AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
|
|
|
+ micspk->input_resample_state = speex_resampler_init(1, CAPTURE_AUDIO_CLOCK, AUDIO_CLOCK, RESAMPLE_QUALITY, NULL);
|
|
|
}
|
|
|
micspk->baudio_device_started_flag = false;
|
|
|
sem_init(micspk->audio_device_started_sem, 0, 0);
|