Код:
diff -r 81bbd579644e softwinner/pmp3670b/libraries/audio/audio_hw.c
--- a/softwinner/pmp3670b/libraries/audio/audio_hw.c Fri Oct 24 19:23:15 2014 +0400
+++ b/softwinner/pmp3670b/libraries/audio/audio_hw.c Sat Oct 25 11:25:12 2014 +0400
@@ -22,6 +22,7 @@
#include <stdint.h>
#include <sys/time.h>
#include <sys/stat.h>
+#include <stdio.h>
#include <stdlib.h>
#include <cutils/log.h>
@@ -239,7 +240,7 @@
},
{
.ctl_name = NULL,
- },
+ },
};
struct route_setting line_in_rec_routing[] = {
@@ -372,6 +373,8 @@
struct echo_reference_itfe *echo_reference;
struct sunxi_audio_device *dev;
int write_threshold;
+ unsigned long *channel_delay;
+ char **delay_chunk;
};
#define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */
@@ -783,6 +786,51 @@
}
}
+static unsigned int audio_format_to_bytes(enum pcm_format format)
+{
+ switch (format) {
+ case PCM_FORMAT_S32_LE:
+ case PCM_FORMAT_S24_LE:
+ return 32 >> 3;
+ default:
+ case PCM_FORMAT_S16_LE:
+ return 16 >> 3;
+ };
+}
+
+static unsigned long get_delay_config (unsigned short channel, uint32_t rate) {
+ unsigned long delay = 0;
+
+ FILE * fp ;
+
+ size_t MAXLINE = 12;
+ char line[MAXLINE];
+
+ unsigned short current_channel = 0;
+ char filename[] = "/etc/audio_delays.conf";
+
+ fp = fopen(filename, "r");
+
+ if(fp != NULL){
+ while(!feof(fp)){
+ fgets(line, MAXLINE, fp);
+ if (current_channel == channel) {
+ delay = (unsigned long)(atof(line) * rate);
+ break;
+ }
+ current_channel++;
+ }
+ } else {
+ delay = 0;
+ }
+
+ if (fp != NULL) {
+ fclose(fp);
+ }
+
+ return delay;
+}
+
/* must be called with hw device and output stream mutexes locked */
static int start_output_stream(struct sunxi_stream_out *out)
{
@@ -891,7 +939,19 @@
out->write_threshold = PLAYBACK_PERIOD_COUNT * LONG_PERIOD_SIZE;
out->config.start_threshold = SHORT_PERIOD_SIZE * 2;
out->config.avail_min = LONG_PERIOD_SIZE;
-
+
+ unsigned long delay_config[out->config.channels];
+ unsigned short channel;
+ char *delay_buffer[out->config.channels];
+
+ for (channel = 0; channel < out->config.channels; channel++) {
+ delay_config[channel] = get_delay_config(channel, out->config.rate);
+ delay_buffer[channel] = malloc(delay_config[channel] * audio_format_to_bytes(out->config.format));
+ memset(delay_buffer[channel],0,delay_config[channel] * audio_format_to_bytes(out->config.format));
+ }
+
+ out->channel_delay = delay_config;
+ out->delay_chunk = delay_buffer;
LOGD("start_output_stream: card:%d, port:%d, rate:%d", card, port, out->config.rate);
// out->pcm = pcm_open_req(card, port, PCM_OUT | PCM_MMAP | PCM_NOIRQ, &out->config, DEFAULT_OUT_SAMPLING_RATE);
@@ -1279,6 +1339,40 @@
out->config.avail_min = SHORT_PERIOD_SIZE;
pcm_set_avail_min(out->pcm, out->config.avail_min);
+ /* applay delays per channel */
+ unsigned short current_channel = 0;
+ unsigned long max_delay_range = 0;
+
+ /* check at least one channel delay present */
+ while(current_channel < out->config.channels) {
+ if (out->channel_delay[current_channel] > max_delay_range)
+ max_delay_range = out->channel_delay[current_channel];
+ current_channel++;
+ }
+
+ if (max_delay_range > 0) {
+ size_t current_frame, current_offset;
+ size_t bytes_in_frame = frame_size/out->config.channels;
+ char *c, *cc;
+
+ cc = malloc(bytes_in_frame);
+ /* shift data in each channel frame by frame */
+ for(current_frame = 0, current_offset = 0;
+ current_frame < in_frames;
+ current_frame++, current_offset += frame_size) {
+ for(current_channel = 0; current_channel < out->config.channels; current_channel++) {
+ if (out->channel_delay[current_channel] > 0) {
+ c = (char *)buffer + current_offset + current_channel*bytes_in_frame;
+
+ memcpy(cc, c, bytes_in_frame);
+ memcpy(c, out->delay_chunk[current_channel], bytes_in_frame);
+ memmove(out->delay_chunk[current_channel],out->delay_chunk[current_channel]+bytes_in_frame,(out->channel_delay[current_channel]-1)*bytes_in_frame);
+ memcpy(out->delay_chunk[current_channel]+(out->channel_delay[current_channel]-1)*bytes_in_frame, cc, bytes_in_frame);
+ }
+ }
+ }
+ }
+
/* only use resampler if required */
if (out->resampler) {
out->resampler->resample_from_input(out->resampler,
@@ -2099,7 +2193,7 @@
*sample_rate = out_get_sample_rate(&out->stream.common);
LOGV("+++++++++++++++ adev_open_output_stream: req_sample_rate: %d, fmt: %x, channel_count: %d",
- *sample_rate, *format, *channels);
+ *sample_rate, *format, *channels);
*stream_out = &out->stream;
return 0;
@@ -2120,6 +2214,8 @@
free(out->buffer);
if (out->resampler)
release_resampler(out->resampler);
+ if (out->delay_chunk)
+ free(out->delay_chunk);
free(stream);
}
Социальные закладки