summaryrefslogtreecommitdiff
authorzhe.wang <zhe.wang@amlogic.com>2014-05-16 07:37:42 (GMT)
committer tao.dong <tao.dong@amlogic.com>2014-05-29 01:27:04 (GMT)
commit18e36ecadc19ae9696061580e1fed7aa72321fd0 (patch)
tree3fa3cd20c34b9fd567b355adccc1ca0082374d59
parenta4e1e138b54dda38ce41fd7fad6bb6b4a4cd14a2 (diff)
downloadaudio-18e36ecadc19ae9696061580e1fed7aa72321fd0.zip
audio-18e36ecadc19ae9696061580e1fed7aa72321fd0.tar.gz
audio-18e36ecadc19ae9696061580e1fed7aa72321fd0.tar.bz2
PD[91923]:1,change a new audio resample Algorithm for USB playback
2,free resample buffer when do standby 3,2 channels input data and 1 channel output resampled data
Diffstat
-rwxr-xr-xAndroid.mk3
-rwxr-xr-xaudio_hw.c13
-rwxr-xr-xaudio_resampler.c103
-rwxr-xr-xaudio_resampler.h19
-rwxr-xr-xusb_audio_hw.c60
5 files changed, 165 insertions, 33 deletions
diff --git a/Android.mk b/Android.mk
index 435614c..039d533 100755
--- a/Android.mk
+++ b/Android.mk
@@ -52,7 +52,8 @@ ifeq ($(strip $(BOARD_ALSA_AUDIO)),tiny)
LOCAL_MODULE := audio.usb.amlogic
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := \
- usb_audio_hw.c
+ usb_audio_hw.c \
+ audio_resampler.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
system/media/audio_utils/include
diff --git a/audio_hw.c b/audio_hw.c
index c53f250..ecd53d3 100755
--- a/audio_hw.c
+++ b/audio_hw.c
@@ -742,6 +742,14 @@ static int do_output_standby(struct aml_stream_out *out)
out->frame_count = 0;
adev->active_output = 0;
+ if (out->buffer){
+ free(out->buffer);
+ out->buffer = NULL;
+ }
+ if (out->resampler){
+ release_resampler(out->resampler);
+ out->resampler = NULL;
+ }
/* if in call, don't turn off the output stage. This will
be done when the call is ended */
if (adev->mode != AUDIO_MODE_IN_CALL) {
@@ -1849,11 +1857,6 @@ static void adev_close_output_stream(struct audio_hw_device *dev,
LOGFUNC("%s(%p, %p)", __FUNCTION__, dev, stream);
out_standby(&stream->common);
- if (out->buffer)
- free(out->buffer);
- if (out->resampler)
- release_resampler(out->resampler);
-
free(stream);
}
diff --git a/audio_resampler.c b/audio_resampler.c
new file mode 100755
index 0000000..7886824
--- a/dev/null
+++ b/audio_resampler.c
@@ -0,0 +1,103 @@
+#include <math.h>
+#include <cutils/log.h>
+
+#include "audio_resampler.h"
+
+#define LOG_TAG "usb_audio_resampler"
+
+//Clip from 16.16 fixed-point to 0.15 fixed-point.
+inline static short clip(int x) {
+ if (x < -32768) {
+ return -32768;
+ } else if (x > 32767) {
+ return 32767;
+ } else {
+ return x;
+ }
+}
+
+int resampler_init(struct resample_para *resample) {
+
+ ALOGD("%s, Init Resampler: input_sr = %d, output_sr = %d \n",
+ __FUNCTION__,resample->input_sr,resample->output_sr);
+
+ static const double kPhaseMultiplier = 1L << 28;
+
+ resample->FractionStep = (unsigned int) (resample->input_sr * kPhaseMultiplier
+ / resample->output_sr);
+ resample->SampleFraction = 0;
+ resample->lastsample_left = 0;
+ resample->lastsample_right = 0;
+ return 0;
+}
+
+int resample_process(struct resample_para *resample, unsigned int in_frame,
+ short* input, short* output) {
+ unsigned int inputIndex = 0;
+ unsigned int outputIndex = 0;
+ unsigned int FractionStep = resample->FractionStep;
+
+ static const unsigned int kPhaseMask = (1LU << 28) - 1;
+ unsigned int frac = resample->SampleFraction;
+ short lastsample_left = resample->lastsample_left;
+ short lastsample_right = resample->lastsample_right;
+
+ if(resample->channels == 2){
+ while (inputIndex == 0) {
+ *output++ = clip((int) lastsample_left +
+ ((((int) input[0] - (int) lastsample_left) * ((int) frac >> 13)) >> 15));
+ *output++ = clip((int) lastsample_right +
+ ((((int) input[1] - (int) lastsample_right) * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ while (inputIndex < in_frame) {
+ *output++ = clip((int) input[2 * inputIndex - 2] + ((((int) input[2 * inputIndex]
+ - (int) input[2 * inputIndex - 2]) * ((int) frac >> 13)) >> 15));
+ *output++ = clip((int) input[2 * inputIndex - 1] + ((((int) input[2 * inputIndex + 1]
+ - (int) input[2 * inputIndex - 1]) * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ resample->lastsample_left = input[2 * in_frame - 2];
+ resample->lastsample_right = input[2 * in_frame - 1];
+ resample->SampleFraction = frac;
+ }else{
+ //left channel as output
+ while (inputIndex == 0) {
+ *output++ = clip((int) lastsample_left +
+ ((((int) input[0] - (int) lastsample_left) * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ while (inputIndex < in_frame) {
+ *output++ = clip((int) input[2 * inputIndex - 2] + ((((int) input[2 * inputIndex]
+ - (int) input[2 * inputIndex - 2]) * ((int) frac >> 13)) >> 15));
+
+ frac += FractionStep;
+ inputIndex += (frac >> 28);
+ frac = (frac & kPhaseMask);
+ outputIndex++;
+ }
+
+ resample->lastsample_left = input[2 * in_frame - 2];
+ resample->SampleFraction = frac;
+ }
+
+ return outputIndex;
+}
+
+
+
diff --git a/audio_resampler.h b/audio_resampler.h
new file mode 100755
index 0000000..e43dfae
--- a/dev/null
+++ b/audio_resampler.h
@@ -0,0 +1,19 @@
+#ifndef __AUDIO_RESAMPLER_H__
+#define __AUDIO_RESAMPLER_H__
+
+struct resample_para {
+ unsigned int FractionStep;
+ unsigned int SampleFraction;
+ short lastsample_left;
+ short lastsample_right;
+ unsigned int input_sr;
+ unsigned int output_sr;
+ unsigned int channels;
+};
+
+int resampler_init(struct resample_para *resample);
+int resample_process(struct resample_para *resample, unsigned int in_frame,
+ short* input, short* output);
+
+
+#endif
diff --git a/usb_audio_hw.c b/usb_audio_hw.c
index 3788f62..a6f72ae 100755
--- a/usb_audio_hw.c
+++ b/usb_audio_hw.c
@@ -36,22 +36,27 @@
#include <tinyalsa/asoundlib.h>
#include <audio_utils/resampler.h>
+#include "audio_resampler.h"
+
#define DEFAULT_OUT_SAMPLING_RATE 44100
#define RESAMPLER_BUFFER_SIZE 4096
+#define DEFAULT_PERIOD_SIZE 1024
+#define PERIOD_COUNT 4
#define BUFFSIZE 100000
+
struct pcm_config pcm_out_config = {
.channels = 2,
.rate = DEFAULT_OUT_SAMPLING_RATE,
- .period_size = 1024,
- .period_count = 4,
+ .period_size = DEFAULT_PERIOD_SIZE,
+ .period_count = PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
struct pcm_config pcm_in_config = {
.channels = 1,
.rate = DEFAULT_OUT_SAMPLING_RATE,
- .period_size = 1024,
- .period_count = 4,
+ .period_size = DEFAULT_PERIOD_SIZE,
+ .period_count = PERIOD_COUNT,
.format = PCM_FORMAT_S16_LE,
};
@@ -75,8 +80,8 @@ struct aml_stream_out {
pthread_mutex_t lock; /* see note below on mutex acquisition order */
struct pcm_config out_config;
struct pcm *out_pcm;
- struct resampler_itfe *resampler;
- char *buffer;
+ struct resample_para resampler;
+ void *buffer;
bool standby;
struct aml_audio_device *dev;
@@ -284,16 +289,15 @@ static int start_output_stream(struct aml_stream_out *out)
return -EINVAL;
}
}
+ out->buffer = NULL;
if (out->out_config.rate != pcm_out_config.rate){
- err = create_resampler(DEFAULT_OUT_SAMPLING_RATE,
- out->out_config.rate,
- 2,
- RESAMPLER_QUALITY_DEFAULT,
- NULL,
- &out->resampler);
- if (err != 0)
- return -ENOMEM;
- out->buffer = malloc(RESAMPLER_BUFFER_SIZE); /* todo: allow for reallocing */
+ out->resampler.input_sr = pcm_out_config.rate;
+ out->resampler.output_sr = out->out_config.rate;
+ out->resampler.channels = out->out_config.channels;
+ resampler_init(&out->resampler);
+ int buffersize = DEFAULT_PERIOD_SIZE * out->out_config.rate / pcm_out_config.rate + 1;
+ out->buffer = malloc(buffersize*4);
+ ALOGE("out->buffer: %p, buffer_size = %d",out->buffer,buffersize);
if (!out->buffer)
return -ENOMEM;
}
@@ -362,7 +366,7 @@ static audio_format_t out_get_format(const struct audio_stream *stream)
return AUDIO_FORMAT_PCM_16_BIT;
}
-static int out_set_format(struct audio_stream *stream, int format)
+static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
ALOGD("%s(%p)", __FUNCTION__, stream);
@@ -375,12 +379,17 @@ static int do_output_standby(struct aml_stream_out *out)
struct aml_audio_device *adev = out->dev;
ALOGD("%s(%p)", __FUNCTION__, out);
-
+
if (!out->standby) {
pcm_close(out->out_pcm);
out->out_pcm = NULL;
adev->active_output = 0;
+
+ if (out->buffer != NULL){
+ free(out->buffer);
+ out->buffer = NULL;
+ }
out->standby = true;
}
return 0;
@@ -447,7 +456,7 @@ static char * out_get_parameters(const struct audio_stream *stream, const char *
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
- struct aml_stream_out *out = (struct stream_out *)stream;
+ struct aml_stream_out *out = (struct aml_stream_out *)stream;
return (pcm_out_config.period_size * pcm_out_config.period_count * 1000) /
out->out_config.rate;
}
@@ -495,18 +504,15 @@ FILE * fp=fopen("/data/audio_in","a+");
#endif
/* only use resampler if required */
if (out->out_config.rate != DEFAULT_OUT_SAMPLING_RATE) {
- out->resampler->resample_from_input(out->resampler,
- (int16_t *)buffer,
- &in_frames,
- (int16_t *)out->buffer,
- &out_frames);
+ out_frames = resample_process(&out->resampler, in_frames,
+ (short *)buffer, (short *)out->buffer);
buf = out->buffer;
} else {
out_frames = in_frames;
buf = (void *)buffer;
}
-
- pcm_write(out->out_pcm, (void *)buf, out_frames * frame_size);
+
+ pcm_write(out->out_pcm, (void *)buf, out_frames * out->out_config.channels * 2);
pthread_mutex_unlock(&out->lock);
pthread_mutex_unlock(&out->dev->lock);
@@ -1140,7 +1146,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev,
{
struct aml_audio_device *adev = (struct aml_audio_device *)dev;
struct aml_stream_in *in;
- struct mixer *usb_mixer;
+ struct mixer *usb_mixer = NULL;
int ret;
in = (struct aml_stream_in *)calloc(1, sizeof(struct aml_stream_in));
@@ -1247,7 +1253,7 @@ static int adev_close(hw_device_t *device)
{
struct aml_audio_device *adev = (struct aml_audio_device *)device;
- // LOGFUNC("%s(%p)", __FUNCTION__, device);
+ ALOGD("%s(%p)", __func__, device);
free(device);
return 0;