GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env make
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright (c) XMEDIA. All rights reserved.
|
||||
#
|
||||
###############################################################################
|
||||
ifeq ($(CFG_XMEDIA_EXPORT_FLAG),)
|
||||
SDK_DIR := $(shell cd $(CURDIR)/../../../../ && /bin/pwd)
|
||||
endif
|
||||
|
||||
include $(SDK_DIR)/build/base.mk
|
||||
|
||||
USER := $(shell whoami)
|
||||
|
||||
CROSS_COMPILE:=$(TOOLCHAIN)
|
||||
|
||||
ALSALIB := alsa-lib-1.1.7
|
||||
|
||||
ALSALIB_BUILDDIR = $(SDK_DIR)/sample/uvc_app/audio/alsa
|
||||
|
||||
ALSALIB_INSTALLDIR = $(ALSALIB_BUILDDIR)/install
|
||||
|
||||
ALSALIB_PREFIX = $(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)/.install
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all:$(ALSALIB_BUILDDIR)/install/lib/libasound.a
|
||||
|
||||
clean: $(ALSALIB).clean
|
||||
|
||||
$(ALSALIB).clean:
|
||||
rm -rf $(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)
|
||||
rm -rf $(ALSALIB_BUILDDIR)/install
|
||||
|
||||
$(ALSALIB_BUILDDIR)/install/lib/libasound.a: $(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)/.built
|
||||
touch $@
|
||||
|
||||
$(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)/.built: $(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)/.extracted
|
||||
cd $(<D); CC=$(CROSS_COMPILE)-gcc STRIP=$(CROSS_COMPILE)-strip ./configure \
|
||||
--prefix=$(ALSALIB_INSTALLDIR) \
|
||||
--host=$(CROSS_COMPILE) \
|
||||
--enable-static=yes \
|
||||
--enable-shared=no \
|
||||
--disable-python \
|
||||
--with-configdir=/home/$(USER)/audio/alsa
|
||||
make -C $(<D)
|
||||
make -C $(<D) install
|
||||
touch $@
|
||||
|
||||
$(ALSALIB_BUILDDIR)/opensource/$(ALSALIB)/.extracted:
|
||||
tar -xjvf $(ALSALIB_BUILDDIR)/opensource/$(ALSALIB).tar.bz2 -C $(ALSALIB_BUILDDIR)/opensource
|
||||
touch $@
|
||||
@@ -0,0 +1,815 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "uac_hal.h"
|
||||
#include "uac_log.h"
|
||||
|
||||
#define UAC_HOST_END 0
|
||||
#define PCM_WAIT_TIME_MS 1000
|
||||
|
||||
struct data_buffer {
|
||||
char* addr;
|
||||
unsigned int size; // The unit is bytes, and the size is equal to period_stize.
|
||||
};
|
||||
|
||||
struct user_args {
|
||||
char id[16];
|
||||
unsigned int rate;
|
||||
unsigned int channels;
|
||||
unsigned int buffer_time;
|
||||
unsigned int period_time;
|
||||
snd_pcm_format_t format;
|
||||
snd_pcm_sframes_t buffer_size; // number of samples, When calculating memory space, it is necessary to convert it into bytes.
|
||||
snd_pcm_sframes_t period_size; // number of samples, When calculating memory space, it is necessary to convert it into bytes.
|
||||
};
|
||||
|
||||
static struct data_buffer g_playback_data = {0};
|
||||
static snd_pcm_t* g_handle_playback = NULL;
|
||||
static struct user_args p_args = {
|
||||
.id = "playback", /* playback */
|
||||
.rate = 16000, /* stream rate */
|
||||
.channels = 1, /* count of channels */
|
||||
.buffer_time = 40000, /* ring buffer length in us */
|
||||
.period_time = 10000, /* period time in us */
|
||||
.format = SND_PCM_FORMAT_S16_LE, /* sample format */
|
||||
};
|
||||
|
||||
static struct data_buffer g_capture_data = {0};
|
||||
static snd_pcm_t* g_handle_capture = NULL;
|
||||
static struct user_args c_args = {
|
||||
.id = "capture", /* capture */
|
||||
.rate = 16000, /* stream rate */
|
||||
.channels = 1, /* count of channels */
|
||||
.buffer_time = 40000, /* ring buffer length in us */
|
||||
.period_time = 10000, /* period time in us */
|
||||
.format = SND_PCM_FORMAT_S16_LE, /* sample format */
|
||||
};
|
||||
|
||||
#if UAC_HOST_END
|
||||
static char *device = "hw:0,0"; /* playback and capture device */
|
||||
#else
|
||||
static char *device = "default"; /* playback and capture device */
|
||||
#endif
|
||||
|
||||
static int g_playback_run = 0;
|
||||
static int g_capture_run = 0;
|
||||
|
||||
static audio_stream_operate_t* uac_stream = NULL;
|
||||
|
||||
/******************************* UAC Stream *******************************************/
|
||||
|
||||
static int uac_stream_config_playback(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_stream_format_t format,
|
||||
int is_interleaved)
|
||||
{
|
||||
if (uac_stream && uac_stream->playback_stream && uac_stream->playback_stream->config) {
|
||||
return uac_stream->playback_stream->config(channels, rate, period_time, format, is_interleaved);
|
||||
} else {
|
||||
uac_loge("Invalid config function for playback stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_startup_playback(void)
|
||||
{
|
||||
if (uac_stream && uac_stream->playback_stream && uac_stream->playback_stream->startup) {
|
||||
return uac_stream->playback_stream->startup();
|
||||
} else {
|
||||
uac_loge("Invalid startup function for playback stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_shutdown_playback(void)
|
||||
{
|
||||
if (uac_stream && uac_stream->playback_stream && uac_stream->playback_stream->shutdown) {
|
||||
return uac_stream->playback_stream->shutdown();
|
||||
} else {
|
||||
uac_loge("Invalid shutdown function for playback stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_recv_from_ai(char* buf, int size, int timeout_ms) {
|
||||
if (uac_stream && uac_stream->playback_stream
|
||||
&& uac_stream->playback_stream->recv_from_stream) {
|
||||
return uac_stream->playback_stream->recv_from_stream(buf, size, timeout_ms);
|
||||
} else {
|
||||
uac_loge("Invalid recv function for playback stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_config_capture(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_stream_format_t format,
|
||||
int is_interleaved)
|
||||
{
|
||||
if (uac_stream && uac_stream->capture_stream && uac_stream->capture_stream->config) {
|
||||
return uac_stream->capture_stream->config(channels, rate, period_time, format, is_interleaved);
|
||||
} else {
|
||||
uac_loge("Invalid contig function for capture stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_startup_capture(void)
|
||||
{
|
||||
if (uac_stream && uac_stream->capture_stream && uac_stream->capture_stream->startup) {
|
||||
return uac_stream->capture_stream->startup();
|
||||
} else {
|
||||
uac_loge("Invalid startup function for capture stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_shutdown_capture(void)
|
||||
{
|
||||
if (uac_stream && uac_stream->capture_stream && uac_stream->capture_stream->shutdown) {
|
||||
return uac_stream->capture_stream->shutdown();
|
||||
} else {
|
||||
uac_loge("Invalid shutdown function for capture.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_stream_send_to_ao(char* buf, int size, int timeout_ms)
|
||||
{
|
||||
if (uac_stream && uac_stream->capture_stream
|
||||
&& uac_stream->capture_stream->send_to_stream) {
|
||||
return uac_stream->capture_stream->send_to_stream(buf, size, timeout_ms);
|
||||
} else {
|
||||
uac_loge("Invalid send function for capture stream.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************************/
|
||||
|
||||
/******************************* UAC Device *******************************************/
|
||||
static int set_hwparams(snd_pcm_t* handle, snd_pcm_hw_params_t* params, struct user_args* args)
|
||||
{
|
||||
int err;
|
||||
unsigned int val, sample_rate;
|
||||
unsigned int channels = args->channels;
|
||||
char* id = (char*)args->id;
|
||||
snd_pcm_format_t format = args->format;
|
||||
snd_pcm_uframes_t frames = 0;
|
||||
|
||||
/* Fill it in with default values. */
|
||||
err = snd_pcm_hw_params_any(handle, params);
|
||||
if (err < 0) {
|
||||
uac_loge("Broken configuration for %s: no configurations available: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the interleaved read/write format */
|
||||
err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0) {
|
||||
uac_loge("Access type not available for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the sample format */
|
||||
err = snd_pcm_hw_params_set_format(handle, params, format);
|
||||
if (err < 0) {
|
||||
uac_loge("Sample format not available for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the count of channels */
|
||||
err = snd_pcm_hw_params_set_channels(handle, params, channels);
|
||||
if (err < 0) {
|
||||
uac_loge("Channels count (%i) not available for %s: %s\n", channels, id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the stream rate */
|
||||
val = args->rate;
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &val, 0);
|
||||
if (err < 0) {
|
||||
uac_loge("Rate %iHz not available for %s: %s\n", args->rate, id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (val != args->rate) {
|
||||
uac_logw("Rate doesn't match for %s: (requested %iHz, get %iHz)\n", id, args->rate, val);
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_rate(params, &sample_rate, 0);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to get rate for %s: %s.\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
args->rate = sample_rate;
|
||||
|
||||
/* set set the period size */
|
||||
frames = sample_rate / 1000 * (args->period_time / 1000);
|
||||
err = snd_pcm_hw_params_set_period_size(handle, params, frames, 0);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set period size %lu for %s: %s.\n", frames, id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_period_size(params, &frames, NULL);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to get period size for %s: %s.\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
args->period_size = frames;
|
||||
|
||||
/* set the buffer size */
|
||||
frames = (args->buffer_time / args->period_time) * args->period_size;
|
||||
err = snd_pcm_hw_params_set_buffer_size(handle, params, frames);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set buffer size %lu for %s: %s.\n", frames, id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_get_buffer_size(params, &frames);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to get buffer size for %s: %s.\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
args->buffer_size = frames;
|
||||
|
||||
/* write the parameters to device */
|
||||
err = snd_pcm_hw_params(handle, params);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For playback
|
||||
static int set_swparams(snd_pcm_t* handle, snd_pcm_sw_params_t* swparams, struct user_args* args)
|
||||
{
|
||||
int err;
|
||||
int period_event = 0; /* produce poll event after each period */
|
||||
char* id = (char*)args->id;
|
||||
snd_pcm_sframes_t buffer_size = args->buffer_size;
|
||||
snd_pcm_sframes_t period_size = args->period_size;
|
||||
|
||||
|
||||
/* get the current swparams */
|
||||
err = snd_pcm_sw_params_current(handle, swparams);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* start the transfer when the buffer is almost full: */
|
||||
/* (buffer_size / avail_min) * avail_min */
|
||||
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* allow the transfer when at least period_size samples can be processed */
|
||||
/* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
|
||||
err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set avail min for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* enable period events when requested */
|
||||
if (period_event) {
|
||||
err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set period event %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* write the parameters to the playback device */
|
||||
err = snd_pcm_sw_params(handle, swparams);
|
||||
if (err < 0) {
|
||||
uac_loge("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_playback_init(void)
|
||||
{
|
||||
// init p_args
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_playback_deinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_playback_open(void)
|
||||
{
|
||||
int err;
|
||||
int buf_size;
|
||||
snd_output_t *output = NULL;
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
snd_pcm_sw_params_t *swparams = NULL;
|
||||
|
||||
err = snd_output_stdio_attach(&output, stdout, 0);
|
||||
if (err < 0) {
|
||||
uac_logw("Output failed: %s\n", snd_strerror(err));
|
||||
}
|
||||
|
||||
err = snd_pcm_open(&g_handle_playback, device, SND_PCM_STREAM_PLAYBACK, 0);
|
||||
if (err < 0) {
|
||||
uac_loge("snd_pcm_open playback failed: %s.\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
err = set_hwparams(g_handle_playback, hwparams, &p_args);
|
||||
if (err < 0) {
|
||||
goto hw_err;
|
||||
}
|
||||
|
||||
err = set_swparams(g_handle_playback, swparams, &p_args);
|
||||
if (err < 0) {
|
||||
goto hw_err;
|
||||
}
|
||||
|
||||
// p_args.period_size : Number of samples per cycle
|
||||
// (p_args.channels * snd_pcm_format_physical_width(p_args.format) / 8) : The number of bytes per sample.
|
||||
buf_size = p_args.period_size * (p_args.channels * snd_pcm_format_physical_width(p_args.format) / 8);
|
||||
g_playback_data.addr = malloc(buf_size);
|
||||
if (g_playback_data.addr == NULL) {
|
||||
uac_loge("No enough memory\n");
|
||||
goto sw_err;
|
||||
}
|
||||
|
||||
g_playback_data.size = buf_size;
|
||||
|
||||
uac_stream_config_playback(p_args.channels,
|
||||
p_args.rate,
|
||||
p_args.period_time / 1000,
|
||||
AUDIO_STREAM_FORMAT_S16_LE,
|
||||
1);
|
||||
|
||||
|
||||
/* show the PCM setup parameters */
|
||||
snd_pcm_dump(g_handle_playback, output);
|
||||
|
||||
return 0;
|
||||
|
||||
hw_err:
|
||||
sw_err:
|
||||
snd_pcm_close(g_handle_playback);
|
||||
g_handle_playback = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int alsa_playback_close(void)
|
||||
{
|
||||
if (g_playback_data.addr != NULL) {
|
||||
free(g_playback_data.addr);
|
||||
g_playback_data.addr = NULL;
|
||||
}
|
||||
|
||||
if (g_handle_playback != NULL) {
|
||||
snd_pcm_close(g_handle_playback);
|
||||
g_handle_playback = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recv audio frame from AI, and send to ALSA */
|
||||
static int alsa_playback_run(int timeout_ms)
|
||||
{
|
||||
int err, cptr;
|
||||
char* buffer = g_playback_data.addr;
|
||||
unsigned int buf_len = g_playback_data.size;
|
||||
unsigned int period_size = p_args.period_size;
|
||||
snd_pcm_t* handle = g_handle_playback;
|
||||
|
||||
uac_logd("Playback stream start\n");
|
||||
memset(buffer, 0, buf_len);
|
||||
err = uac_stream_recv_from_ai(buffer, buf_len, timeout_ms);
|
||||
if (err < 0) {
|
||||
uac_loge("recv stream from ai failed.\n");
|
||||
//return -1;
|
||||
}
|
||||
|
||||
cptr = period_size;
|
||||
while (cptr > 0 && g_playback_run) {
|
||||
err = snd_pcm_wait(handle, timeout_ms);
|
||||
if (err == 0) {
|
||||
// If the other end keeps not taking data, the buffer will be continuously timed out after being consumed.
|
||||
uac_logd("Playback pcm wait timeout(%dms)\n", timeout_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
err = snd_pcm_writei(handle, buffer, cptr);
|
||||
#if 1
|
||||
if (err == -EPIPE) {
|
||||
/* EPIPE means underrun */
|
||||
uac_loge("Playback underrun occurred, %s\n", snd_strerror(err));
|
||||
snd_pcm_prepare(handle);
|
||||
snd_pcm_start(handle);
|
||||
continue;
|
||||
} else if (err < 0) {
|
||||
uac_loge("Playback writei error: %s\n", snd_strerror(err));
|
||||
break;
|
||||
} else if (err != cptr) {
|
||||
uac_logi("Short write (expected %u, wrote %d)\n", cptr, err);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (err < 0) {
|
||||
err = snd_pcm_recover(handle, err, 0);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
cptr -= err;
|
||||
}
|
||||
uac_logd("Playback stream ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_playback_stop(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_capture_init(void)
|
||||
{
|
||||
// init c_args
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_capture_deinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_capture_open(void)
|
||||
{
|
||||
int err;
|
||||
int buf_size;
|
||||
snd_output_t *output = NULL;
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
|
||||
err = snd_output_stdio_attach(&output, stdout, 0);
|
||||
if (err < 0) {
|
||||
uac_logw("Output failed: %s\n", snd_strerror(err));
|
||||
}
|
||||
|
||||
err = snd_pcm_open(&g_handle_capture, device, SND_PCM_STREAM_CAPTURE, 0);
|
||||
if (err < 0) {
|
||||
uac_loge("snd_pcm_open capture failed: %s.\n", snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
|
||||
err = set_hwparams(g_handle_capture, hwparams, &c_args);
|
||||
if (err < 0) {
|
||||
goto hw_err;
|
||||
}
|
||||
|
||||
buf_size = (c_args.period_size * c_args.channels * snd_pcm_format_physical_width(c_args.format)) / 8;
|
||||
g_capture_data.addr = malloc(buf_size);
|
||||
if (g_capture_data.addr == NULL) {
|
||||
uac_loge("No enough memory\n");
|
||||
goto hw_err;
|
||||
}
|
||||
|
||||
g_capture_data.size = buf_size;
|
||||
|
||||
uac_stream_config_capture(c_args.channels,
|
||||
c_args.rate,
|
||||
c_args.period_time / 1000,
|
||||
AUDIO_STREAM_FORMAT_S16_LE,
|
||||
1);
|
||||
|
||||
/* show the PCM setup parameters */
|
||||
snd_pcm_dump(g_handle_capture, output);
|
||||
|
||||
err = snd_pcm_start(g_handle_capture);
|
||||
if (err < 0) {
|
||||
uac_loge("snd_pcm_start capture failed: %s.\n", snd_strerror(err));
|
||||
goto sw_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
sw_err:
|
||||
if (g_capture_data.addr != NULL) {
|
||||
free(g_capture_data.addr);
|
||||
g_capture_data.addr = NULL;
|
||||
g_capture_data.size = 0;
|
||||
}
|
||||
|
||||
hw_err:
|
||||
snd_pcm_close(g_handle_capture);
|
||||
g_handle_capture = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int alsa_capture_close(void)
|
||||
{
|
||||
if (g_capture_data.addr != NULL) {
|
||||
free(g_capture_data.addr);
|
||||
g_capture_data.addr = NULL;
|
||||
}
|
||||
|
||||
if (g_handle_capture != NULL) {
|
||||
snd_pcm_close(g_handle_capture);
|
||||
g_handle_capture = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recv sample frame from ALSA, and send to AO */
|
||||
static int alsa_capture_run(int timeout_ms)
|
||||
{
|
||||
int err = 0;
|
||||
char* buffer = g_capture_data.addr;
|
||||
int size = g_capture_data.size;
|
||||
unsigned int period_size = c_args.period_size;
|
||||
snd_pcm_t* handle = g_handle_capture;
|
||||
|
||||
uac_logd("Capture stream send start.\n");
|
||||
while (err != period_size && g_capture_run) {
|
||||
err = snd_pcm_wait(handle, timeout_ms);
|
||||
if (err == 0) {
|
||||
uac_logd("Capture pcm wait timeout(%dms).\n", timeout_ms);
|
||||
continue;
|
||||
}
|
||||
|
||||
err = snd_pcm_readi(handle, buffer, period_size);
|
||||
if (err == -EPIPE) {
|
||||
/* EPIPE means overrun */
|
||||
uac_logw("Capture overrun occurred: %s.\n", snd_strerror(err));
|
||||
snd_pcm_prepare(handle);
|
||||
snd_pcm_start(handle);
|
||||
continue;
|
||||
} else if (err < 0) {
|
||||
uac_logw("Capture read failed: %s.\n", snd_strerror(err));
|
||||
continue;
|
||||
} else if (err != (int)period_size) {
|
||||
uac_logw("Short read (expected %u, rrote %d).\n", period_size, err);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uac_stream_send_to_ao(buffer, size, timeout_ms) < 0) {
|
||||
uac_loge("Send to ao failed.\n");
|
||||
} else {
|
||||
uac_logd("Send to ao ok.\n");
|
||||
}
|
||||
}
|
||||
|
||||
uac_logd("Capture stream send ok.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alsa_capture_stop(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/**************************************************************************************/
|
||||
|
||||
static pthread_t pid_playback = -1;
|
||||
static pthread_t pid_capture = -1;
|
||||
|
||||
static void* playback_process(void* args)
|
||||
{
|
||||
uac_logt("UAC playbcak process start.\n");
|
||||
uac_stream_startup_playback();
|
||||
// Waiting for AI to cache data, avoiding the issue of also underrun.
|
||||
usleep(20 * 1000);
|
||||
while (g_playback_run) {
|
||||
//alsa_playback_run(p_args.period_time / 1000);
|
||||
alsa_playback_run(PCM_WAIT_TIME_MS);
|
||||
}
|
||||
|
||||
alsa_playback_stop();
|
||||
uac_stream_shutdown_playback();
|
||||
uac_logt("UAC playback process exit.\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* capture_process(void* args)
|
||||
{
|
||||
uac_logt("UAC capture process start.\n");
|
||||
uac_stream_startup_capture();
|
||||
while (g_capture_run) {
|
||||
//alsa_capture_run(c_args.period_time / 1000);
|
||||
alsa_capture_run(PCM_WAIT_TIME_MS);
|
||||
}
|
||||
|
||||
alsa_capture_stop();
|
||||
uac_stream_shutdown_capture();
|
||||
uac_logt("UAC capture process exit.\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************** UAC Interface *****************************************/
|
||||
static int __uac_dev_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = alsa_playback_init();
|
||||
if (err < 0) {
|
||||
uac_loge("Playback init failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = alsa_capture_init();
|
||||
if (err < 0) {
|
||||
uac_loge("Capture init failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_dev_deinit(void)
|
||||
{
|
||||
alsa_playback_deinit();
|
||||
alsa_capture_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_dev_open(void)
|
||||
{
|
||||
alsa_playback_open();
|
||||
alsa_capture_open();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_dev_close(void)
|
||||
{
|
||||
alsa_playback_close();
|
||||
alsa_capture_close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_dev_run(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
uac_logt("UAC run entry.\n");
|
||||
g_playback_run = 1;
|
||||
err = pthread_create(&pid_playback, NULL, &playback_process, NULL);
|
||||
if (err != 0) {
|
||||
uac_loge("Create playback_process failed.\n");
|
||||
}
|
||||
|
||||
g_capture_run = 1;
|
||||
err = pthread_create(&pid_capture, NULL, &capture_process, NULL);
|
||||
if (err != 0) {
|
||||
uac_loge("Creat capture_process failed.\n");
|
||||
}
|
||||
uac_logt("UAC run ok.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_dev_stop(void)
|
||||
{
|
||||
uac_logt("UAC stop entry.\n");
|
||||
g_playback_run = 0;
|
||||
g_capture_run = 0;
|
||||
pthread_join(pid_playback, NULL);
|
||||
pthread_join(pid_capture, NULL);
|
||||
uac_logt("UAC stop ok.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uac_dev_t uac_dev = {
|
||||
.init = &__uac_dev_init,
|
||||
.deinit = &__uac_dev_deinit,
|
||||
.open = &__uac_dev_open,
|
||||
.close = &__uac_dev_close,
|
||||
.run = &__uac_dev_run,
|
||||
.stop = &__uac_dev_stop,
|
||||
};
|
||||
|
||||
uac_dev_t* get_uac_dev(void)
|
||||
{
|
||||
return &uac_dev;
|
||||
}
|
||||
|
||||
#define check_func(func_ptr, name) do { \
|
||||
if (func_ptr == NULL) { \
|
||||
uac_loge("Invalid %s function.\n", name); \
|
||||
return -1; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int uac_check_strem_func(audio_stream_dev_t* func, int is_playback)
|
||||
{
|
||||
check_func(func->config, "config");
|
||||
check_func(func->startup, "startup");
|
||||
check_func(func->shutdown, "shutdown");
|
||||
if (is_playback) {
|
||||
check_func(func->recv_from_stream, "recv stream");
|
||||
} else {
|
||||
check_func(func->send_to_stream, "send stream");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uac_stream_register(audio_stream_operate_t* hand)
|
||||
{
|
||||
if (hand == NULL) {
|
||||
uac_loge("Invalid stream operate function.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hand->playback_stream == NULL) {
|
||||
uac_loge("Invalid playback_stream.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hand->capture_stream == NULL) {
|
||||
uac_loge("Invalid capture_stream.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uac_check_strem_func(hand->playback_stream, 1) < 0) {
|
||||
uac_loge("Invalid playback operate function.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uac_check_strem_func(hand->capture_stream, 0) < 0) {
|
||||
uac_loge("Invalid capture operate function.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uac_stream = hand;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uac_stream_unregister(void)
|
||||
{
|
||||
uac_stream = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************************/
|
||||
|
||||
/****************************** main **************************************************/
|
||||
#if 0
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
uac_dev_t* uac = get_uac_dev();
|
||||
|
||||
if (uac) {
|
||||
uac_dev->init();
|
||||
uac_dev->open();
|
||||
uac_dev->run();
|
||||
uac_dev->stop();
|
||||
uac_dev->close();
|
||||
uac_dev->deinit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/**************************************************************************************/
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UAC_HAL_H__
|
||||
#define __UAC_HAL_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum audio_stream_format {
|
||||
AUDIO_STREAM_FORMAT_UNKNOWN = -1,
|
||||
/** Signed 8 bit */
|
||||
AUDIO_STREAM_FORMAT_S8 = 0,
|
||||
/** Unsigned 8 bit */
|
||||
AUDIO_STREAM_FORMAT_U8,
|
||||
/** Signed 16 bit Little Endian */
|
||||
AUDIO_STREAM_FORMAT_S16_LE,
|
||||
/** Signed 16 bit Big Endian */
|
||||
AUDIO_STREAM_FORMAT_S16_BE,
|
||||
/** Unsigned 16 bit Little Endian */
|
||||
AUDIO_STREAM_FORMAT_U16_LE,
|
||||
/** Unsigned 16 bit Big Endian */
|
||||
AUDIO_STREAM_FORMAT_U16_BE,
|
||||
/** Signed 24 bit Little Endian using low three bytes in 32-bit word */
|
||||
AUDIO_STREAM_FORMAT_S24_LE,
|
||||
/** Signed 24 bit Big Endian using low three bytes in 32-bit word */
|
||||
AUDIO_STREAM_FORMAT_S24_BE,
|
||||
/** Unsigned 24 bit Little Endian using low three bytes in 32-bit word */
|
||||
AUDIO_STREAM_FORMAT_U24_LE,
|
||||
/** Unsigned 24 bit Big Endian using low three bytes in 32-bit word */
|
||||
AUDIO_STREAM_FORMAT_U24_BE,
|
||||
/** Signed 32 bit Little Endian */
|
||||
AUDIO_STREAM_FORMAT_S32_LE,
|
||||
/** Signed 32 bit Big Endian */
|
||||
AUDIO_STREAM_FORMAT_S32_BE,
|
||||
/** Unsigned 32 bit Little Endian */
|
||||
AUDIO_STREAM_FORMAT_U32_LE,
|
||||
/** Unsigned 32 bit Big Endian */
|
||||
AUDIO_STREAM_FORMAT_U32_BE,
|
||||
} audio_stream_format_t;
|
||||
|
||||
typedef struct {
|
||||
int (*config)(unsigned int channels, unsigned int rate, unsigned int period_time,
|
||||
audio_stream_format_t format, bool is_interleaved);
|
||||
int (*startup)(void);
|
||||
int (*shutdown)(void);
|
||||
int (*recv_from_stream)(char* buf, int size, int timeout_ms);
|
||||
int (*send_to_stream)(char* buf, int size, int timeout_ms);
|
||||
} audio_stream_dev_t;
|
||||
|
||||
typedef struct {
|
||||
/* Get data from stream dev(AI) and send to uac dev */
|
||||
audio_stream_dev_t* playback_stream;
|
||||
/* Get data from uac dev and send to stream dev(AO) */
|
||||
audio_stream_dev_t* capture_stream;
|
||||
} audio_stream_operate_t;
|
||||
|
||||
typedef struct uac_dev {
|
||||
int (*init)(void);
|
||||
int (*deinit)(void);
|
||||
int (*open)(void);
|
||||
int (*close)(void);
|
||||
int (*run)(void);
|
||||
int (*stop)(void);
|
||||
} uac_dev_t;
|
||||
|
||||
uac_dev_t* get_uac_dev(void);
|
||||
int uac_stream_register(audio_stream_operate_t* hand);
|
||||
int uac_stream_unregister(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "uac_hal.h"
|
||||
#include "audio_stream.h"
|
||||
#include "sample_audio.h"
|
||||
|
||||
#include "uac_log.h"
|
||||
|
||||
struct audio_format_map {
|
||||
audio_stream_format_t hal_format;
|
||||
audio_bit_depth bit_format;
|
||||
};
|
||||
|
||||
struct audio_format_map format_group[] = {
|
||||
{AUDIO_STREAM_FORMAT_S8, AUDIO_BIT_DEPTH_8},
|
||||
{AUDIO_STREAM_FORMAT_S16_LE, AUDIO_BIT_DEPTH_16},
|
||||
{AUDIO_STREAM_FORMAT_S24_LE, AUDIO_BIT_DEPTH_24},
|
||||
{AUDIO_STREAM_FORMAT_S32_LE, AUDIO_BIT_DEPTH_32},
|
||||
};
|
||||
|
||||
static int format_hal_to_bit(audio_stream_format_t format)
|
||||
{
|
||||
int i;
|
||||
int nums = sizeof(format_group) / sizeof(struct audio_format_map);
|
||||
|
||||
for (i = 0; i < nums; i++) {
|
||||
if (format_group[i].hal_format == format) {
|
||||
return format_group[i].bit_format;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int playback_stream_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_stream_format_t format,
|
||||
bool is_interleaved)
|
||||
{
|
||||
audio_bit_depth bit_format = format_hal_to_bit(format);
|
||||
|
||||
uac_logd("channels: %u\n", channels);
|
||||
uac_logd("rate: %u\n", rate);
|
||||
uac_logd("period_time: %ums\n", period_time);
|
||||
uac_logd("format: %d\n", bit_format);
|
||||
uac_logd("interleaved: %d\n", is_interleaved);
|
||||
|
||||
return sample_audio_ai_config(channels, rate, period_time, bit_format, is_interleaved);
|
||||
}
|
||||
|
||||
static int playback_stream_startup(void)
|
||||
{
|
||||
return sample_audio_ai_startup();
|
||||
}
|
||||
|
||||
static int playback_stream_shutdown(void)
|
||||
{
|
||||
return sample_audio_ai_shutdown();
|
||||
}
|
||||
|
||||
/* Get stream from AI */
|
||||
static int playback_recv_from_stream(char* buf, int size, int timeout_ms)
|
||||
{
|
||||
return sample_audio_get_frame_from_ai(buf, size, timeout_ms);
|
||||
}
|
||||
|
||||
static int capture_stream_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_stream_format_t format,
|
||||
bool is_interleaved)
|
||||
{
|
||||
audio_bit_depth bit_format = format_hal_to_bit(format);
|
||||
|
||||
uac_logd("channels: %u\n", channels);
|
||||
uac_logd("rate: %u\n", rate);
|
||||
uac_logd("period_time: %ums\n", period_time);
|
||||
uac_logd("format: %d\n", bit_format);
|
||||
uac_logd("interleaved: %d\n", is_interleaved);
|
||||
|
||||
return sample_audio_ao_config(channels, rate, period_time, bit_format, is_interleaved);
|
||||
}
|
||||
|
||||
static int capture_stream_startup(void)
|
||||
{
|
||||
return sample_audio_ao_startup();
|
||||
}
|
||||
|
||||
static int capture_stream_shutdown(void)
|
||||
{
|
||||
return sample_audio_ao_shutdown();
|
||||
}
|
||||
|
||||
/* Send stream to AO */
|
||||
static int capture_send_to_stream(char* buf, int size, int timeout_ms)
|
||||
{
|
||||
return sample_audio_send_frame_to_ao(buf, size, timeout_ms);
|
||||
}
|
||||
|
||||
static audio_stream_dev_t playback_stream_dev = {
|
||||
.config = playback_stream_config,
|
||||
.startup = playback_stream_startup,
|
||||
.shutdown = playback_stream_shutdown,
|
||||
.recv_from_stream = playback_recv_from_stream,
|
||||
};
|
||||
|
||||
static audio_stream_dev_t capture_stream_dev = {
|
||||
.config = capture_stream_config,
|
||||
.startup = capture_stream_startup,
|
||||
.shutdown = capture_stream_shutdown,
|
||||
.send_to_stream = capture_send_to_stream,
|
||||
};
|
||||
|
||||
static audio_stream_operate_t strem_operate = {
|
||||
.playback_stream = &playback_stream_dev,
|
||||
.capture_stream = &capture_stream_dev,
|
||||
};
|
||||
|
||||
audio_stream_operate_t* get_audio_stream(void)
|
||||
{
|
||||
return &strem_operate;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __AUDIO_STREAM_H__
|
||||
#define __AUDIO_STREAM_H__
|
||||
|
||||
#include "uac_hal.h"
|
||||
|
||||
audio_stream_operate_t* get_audio_stream(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "xmedia_audio_common.h"
|
||||
#include "xmedia_audio_ai.h"
|
||||
//#include "xmedia_audio_vqe_common.h"
|
||||
#include "xmedia_audio_vqe.h"
|
||||
#include "xmedia_audio_vqe_enhance_v1.h"
|
||||
|
||||
#include "sample_comm_audio.h"
|
||||
|
||||
#include "sample_audio.h"
|
||||
#include "uac_log.h"
|
||||
|
||||
#define SAMPLE_AUDIO_DBG printf
|
||||
#define FRAME_TIME 10 //ms
|
||||
|
||||
// XMEDIA_AI_DEV_ADC0
|
||||
// XMEDIA_AI_DEV_I2S0
|
||||
// XMEDIA_AI_DEV_PDM0
|
||||
// XMEDIA_AI_DEV_PDM_I2S0
|
||||
#define AI_DEV XMEDIA_AI_DEV_ADC0
|
||||
#define AI_CHANNELS 1
|
||||
|
||||
// XMEDIA_AO_DEV_DAC0
|
||||
// XMEDIA_AO_DEV_I2S0
|
||||
#define AO_DEV XMEDIA_AO_DEV_DAC0
|
||||
#define AO_CHANNELS 1
|
||||
|
||||
static pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define sample_audio_lock() pthread_mutex_lock(&mutex_lock)
|
||||
#define sample_audio_unlock() pthread_mutex_unlock(&mutex_lock)
|
||||
|
||||
#define MIN(val1, val2) ((val1) > (val2) ? (val2) : (val1))
|
||||
|
||||
struct user_args {
|
||||
unsigned int channels;
|
||||
unsigned int sample_rate;
|
||||
unsigned int period_time; /* ms */
|
||||
unsigned int format; /* audio_bit_depth */
|
||||
bool is_interleaved;
|
||||
};
|
||||
|
||||
static unsigned int g_audio_init = 0;
|
||||
|
||||
static sample_ai_config g_ai_config = {
|
||||
.dev = AI_DEV,
|
||||
};
|
||||
static ai_vqe_attr_v1 ai_vqev1_attr = {0};
|
||||
static struct user_args g_ai_args = {
|
||||
.channels = AI_CHANNELS,
|
||||
.sample_rate = AUDIO_SAMPLE_RATE_8000,
|
||||
.period_time = FRAME_TIME,
|
||||
.format = AUDIO_BIT_DEPTH_16,
|
||||
.is_interleaved = 1,
|
||||
};
|
||||
|
||||
static sample_ao_config g_ao_config = {
|
||||
.dev = AO_DEV,
|
||||
};
|
||||
static ao_vqe_attr_v1 ao_vqev1_attr = {0};
|
||||
static struct user_args g_ao_args = {
|
||||
.channels = AO_CHANNELS,
|
||||
.sample_rate = AUDIO_SAMPLE_RATE_8000,
|
||||
.period_time = FRAME_TIME,
|
||||
.format = AUDIO_BIT_DEPTH_16,
|
||||
.is_interleaved = 1,
|
||||
};
|
||||
|
||||
static xmedia_void load_ai_vqev1_attr(ai_vqe_attr* attr)
|
||||
{
|
||||
ai_vqe_attr_v1 *vqev1_attr = &ai_vqev1_attr;
|
||||
|
||||
attr->version = AI_VQE_ENHANCE_ATTR_VERSION_1;
|
||||
attr->work_sample_rate = (g_ai_args.sample_rate == AUDIO_SAMPLE_RATE_8000) ?
|
||||
AUDIO_SAMPLE_RATE_8000 : AUDIO_SAMPLE_RATE_16000;
|
||||
attr->in_channels = g_ai_args.channels;
|
||||
attr->attr = (xmedia_void*)&ai_vqev1_attr;
|
||||
|
||||
vqev1_attr->mask = VQE_V1_MASK_AGC | VQE_V1_MASK_ANR | VQE_V1_MASK_HPF;
|
||||
|
||||
vqev1_attr->agc_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->agc_attr.target_level = -6;
|
||||
vqev1_attr->agc_attr.max_boost_gain = 20;
|
||||
vqev1_attr->agc_attr.noise_floor = -100;
|
||||
vqev1_attr->agc_attr.ratio = 12;
|
||||
vqev1_attr->agc_attr.attack_time = 8;
|
||||
vqev1_attr->agc_attr.release_time =20;
|
||||
|
||||
vqev1_attr->anr_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->anr_attr.usr_scene = VQE_V1_ANR_SCENE_NORMAL;
|
||||
vqev1_attr->anr_attr.nr_mode = VQE_V1_NR_MODE_SPEECH;
|
||||
vqev1_attr->anr_attr.max_suppress_gain = 6;
|
||||
vqev1_attr->anr_attr.suppress_level = 0x2;
|
||||
vqev1_attr->anr_attr.nonstationary_suppress_level = 0x0;
|
||||
|
||||
vqev1_attr->vad_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->vad_attr.sensitivity_level = 4;
|
||||
|
||||
vqev1_attr->hpf_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->hpf_attr.freq = VQE_V1_HPF_FREQ_80;
|
||||
|
||||
memset(&vqev1_attr->eq_attr, 0, sizeof(vqe_eq_attr_v1));
|
||||
|
||||
vqev1_attr->eq_attr.gain[0] = 0;
|
||||
vqev1_attr->eq_attr.gain[1] = 0;
|
||||
vqev1_attr->eq_attr.gain[2] = 0;
|
||||
vqev1_attr->eq_attr.gain[3] = 0;
|
||||
vqev1_attr->eq_attr.gain[4] = 0;
|
||||
vqev1_attr->eq_attr.gain[5] = 0;
|
||||
vqev1_attr->eq_attr.gain[6] = 0;
|
||||
vqev1_attr->eq_attr.gain[7] = 0;
|
||||
vqev1_attr->eq_attr.gain[8] = 0;
|
||||
vqev1_attr->eq_attr.gain[9] = 0;
|
||||
vqev1_attr->eq_attr.gain[10] = 0;
|
||||
vqev1_attr->eq_attr.gain[11] = 0;
|
||||
vqev1_attr->eq_attr.gain[12] = 0;
|
||||
vqev1_attr->eq_attr.gain[13] = 0;
|
||||
vqev1_attr->eq_attr.gain[14] = 0;
|
||||
vqev1_attr->eq_attr.gain[15] = 0;
|
||||
vqev1_attr->eq_attr.gain[16] = 0;
|
||||
vqev1_attr->eq_attr.gain[17] = 0;
|
||||
vqev1_attr->eq_attr.gain[18] = 0;
|
||||
vqev1_attr->eq_attr.gain[19] = 0;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_ai_config_init(xmedia_void)
|
||||
{
|
||||
g_ai_config.dev = AI_DEV;
|
||||
|
||||
sample_comm_ai_get_default_attr(g_ai_config.dev, &g_ai_config.dev_attr);
|
||||
g_ai_config.dev_attr.mode = AUDIO_DEV_WORK_MODE_MONO;
|
||||
g_ai_config.dev_attr.channels = g_ai_args.channels;
|
||||
g_ai_config.dev_attr.bit_depth = g_ai_args.format;
|
||||
g_ai_config.dev_attr.sample_rate = g_ai_args.sample_rate;
|
||||
//g_ai_config.dev_attr.pcm_frame_num = ;
|
||||
g_ai_config.dev_attr.pcm_samples_per_frame = g_ai_args.period_time * g_ai_args.sample_rate / 1000;
|
||||
|
||||
g_ai_config.chn_attr.sample_rate = g_ai_args.sample_rate;
|
||||
g_ai_config.chn_attr.interleaved = g_ai_args.is_interleaved;
|
||||
|
||||
g_ai_config.res_enable = XMEDIA_FALSE;
|
||||
if ((g_ai_config.dev_attr.sample_rate != AUDIO_SAMPLE_RATE_8000 &&
|
||||
g_ai_config.dev_attr.sample_rate != AUDIO_SAMPLE_RATE_16000) ||
|
||||
(g_ai_config.chn_attr.sample_rate != g_ai_config.dev_attr.sample_rate)) {
|
||||
g_ai_config.res_enable = XMEDIA_TRUE;
|
||||
}
|
||||
|
||||
g_ai_config.vqe_enable = XMEDIA_TRUE;
|
||||
load_ai_vqev1_attr(&g_ai_config.vqe_attr);
|
||||
|
||||
g_ai_config.source = AI_EC_SOURCE_AO_DAC0;
|
||||
g_ai_config.ec_chn_id = 0;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_start_ai()
|
||||
{
|
||||
xmedia_s32 ret, vol;
|
||||
|
||||
ret = sample_ai_config_init();
|
||||
CHECK_RET(ret, "sample_ai_config_init");
|
||||
|
||||
ret = sample_comm_ai_register(ai_vqev1_attr.mask, g_ai_config.vqe_attr.version, g_ai_config.res_enable);
|
||||
CHECK_RET(ret, "sample_comm_ai_register");
|
||||
|
||||
ret = sample_comm_ai_start(&g_ai_config);
|
||||
CHECK_RET(ret, "sample_comm_ai_start");
|
||||
|
||||
vol = 10;
|
||||
ret = sample_comm_ai_set_volume(&g_ai_config, vol);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
uac_logw("Set ai volume %d return 0x%x.\n", vol, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_stop_ai(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = sample_comm_ai_stop(&g_ai_config);
|
||||
CHECK_RET(ret, "sample_comm_ai_stop");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_recv_frame_from_ai(char* buf, int size, int time_out)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
audio_frame frame;
|
||||
audio_ext_frame ext_frame;
|
||||
xmedia_u32 copy_size;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < g_ai_config.dev_attr.channels; i++) {
|
||||
ret = xmedia_ai_acquire_frame(g_ai_config.dev, i, &frame, &ext_frame, time_out);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
uac_loge("Acquire audio frame from AI failed, error=%d.\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
copy_size = MIN(size, frame.size);
|
||||
|
||||
if (size != frame.size) {
|
||||
uac_logw("frame.size(%d) != buf.size(%d).\n", frame.size, size);
|
||||
}
|
||||
|
||||
memcpy(buf, frame.data, copy_size);
|
||||
|
||||
xmedia_ai_release_frame(g_ai_config.dev, i, &frame, &ext_frame);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xmedia_void load_ao_vqev1_attr(ao_vqe_attr* attr)
|
||||
{
|
||||
ao_vqe_attr_v1 *vqev1_attr = &ao_vqev1_attr;
|
||||
|
||||
attr->version = AO_VQE_ENHANCE_ATTR_VERSION_1;
|
||||
attr->attr = (xmedia_void*)&ao_vqev1_attr;
|
||||
|
||||
vqev1_attr->mask = VQE_V1_MASK_AGC | VQE_V1_MASK_ANR | VQE_V1_MASK_HPF;
|
||||
|
||||
vqev1_attr->agc_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->agc_attr.target_level = -6;
|
||||
vqev1_attr->agc_attr.max_boost_gain = 20;
|
||||
vqev1_attr->agc_attr.noise_floor = -65;
|
||||
vqev1_attr->agc_attr.ratio = 10;
|
||||
vqev1_attr->agc_attr.attack_time = 20;
|
||||
vqev1_attr->agc_attr.release_time =20;
|
||||
|
||||
vqev1_attr->anr_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->anr_attr.usr_scene = VQE_V1_ANR_SCENE_NORMAL;
|
||||
vqev1_attr->anr_attr.nr_mode = VQE_V1_NR_MODE_SPEECH;
|
||||
vqev1_attr->anr_attr.max_suppress_gain = 6;
|
||||
vqev1_attr->anr_attr.suppress_level = 0x2;
|
||||
vqev1_attr->anr_attr.nonstationary_suppress_level = 0x2;
|
||||
|
||||
vqev1_attr->hpf_attr.mode = VQE_V1_USR_MODE_AUTO;
|
||||
vqev1_attr->hpf_attr.freq = VQE_V1_HPF_FREQ_80;
|
||||
|
||||
memset(&vqev1_attr->eq_attr, 0, sizeof(vqe_eq_attr_v1));
|
||||
|
||||
vqev1_attr->eq_attr.gain[0] = 0;
|
||||
vqev1_attr->eq_attr.gain[1] = 0;
|
||||
vqev1_attr->eq_attr.gain[2] = 0;
|
||||
vqev1_attr->eq_attr.gain[3] = 0;
|
||||
vqev1_attr->eq_attr.gain[4] = 0;
|
||||
vqev1_attr->eq_attr.gain[5] = 0;
|
||||
vqev1_attr->eq_attr.gain[6] = 0;
|
||||
vqev1_attr->eq_attr.gain[7] = 0;
|
||||
vqev1_attr->eq_attr.gain[8] = 0;
|
||||
vqev1_attr->eq_attr.gain[9] = 0;
|
||||
vqev1_attr->eq_attr.gain[10] = 0;
|
||||
vqev1_attr->eq_attr.gain[11] = 0;
|
||||
vqev1_attr->eq_attr.gain[12] = 0;
|
||||
vqev1_attr->eq_attr.gain[13] = 0;
|
||||
vqev1_attr->eq_attr.gain[14] = 0;
|
||||
vqev1_attr->eq_attr.gain[15] = 0;
|
||||
vqev1_attr->eq_attr.gain[16] = 0;
|
||||
vqev1_attr->eq_attr.gain[17] = 0;
|
||||
vqev1_attr->eq_attr.gain[18] = 0;
|
||||
vqev1_attr->eq_attr.gain[19] = 0;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_ao_config_init(xmedia_void)
|
||||
{
|
||||
g_ao_config.dev = AO_DEV;
|
||||
|
||||
sample_comm_ao_get_default_attr(g_ao_config.dev, &g_ao_config.dev_attr);
|
||||
g_ao_config.dev_attr.mode = AUDIO_DEV_WORK_MODE_MONO;
|
||||
g_ao_config.dev_attr.channels = g_ao_args.channels;
|
||||
g_ao_config.dev_attr.bit_depth = g_ao_args.format;
|
||||
g_ao_config.dev_attr.sample_rate = g_ao_args.sample_rate;
|
||||
//g_ao_config.dev_attr.pcm_frame_max_num = ;
|
||||
g_ao_config.dev_attr.pcm_samples_per_frame = g_ao_args.period_time * g_ao_args.sample_rate / 1000;
|
||||
|
||||
g_ao_config.res_enable = XMEDIA_FALSE;
|
||||
if ((g_ao_config.dev_attr.sample_rate != AUDIO_SAMPLE_RATE_8000 &&
|
||||
g_ao_config.dev_attr.sample_rate != AUDIO_SAMPLE_RATE_16000) ||
|
||||
(g_ao_config.frame_info.frm_rate != g_ao_config.dev_attr.sample_rate)) {
|
||||
g_ao_config.res_enable = XMEDIA_TRUE;
|
||||
}
|
||||
|
||||
g_ao_config.vqe_enable = XMEDIA_TRUE;
|
||||
load_ao_vqev1_attr(&g_ao_config.vqe_attr);
|
||||
//g_ao_config.binder_src = ;
|
||||
|
||||
g_ao_config.frame_info.frm_rate = g_ao_args.sample_rate;
|
||||
g_ao_config.frame_info.frm_chn = g_ao_args.channels;
|
||||
g_ao_config.frame_info.frm_bit = g_ao_args.format;
|
||||
|
||||
return XMEDIA_SUCCESS;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_start_ao()
|
||||
{
|
||||
xmedia_s32 ret, vol;
|
||||
|
||||
ret = sample_ao_config_init();
|
||||
CHECK_RET(ret, "sample_ao_config_init");
|
||||
|
||||
ret = sample_comm_ao_register(ao_vqev1_attr.mask, g_ao_config.vqe_attr.version, g_ao_config.res_enable);
|
||||
CHECK_RET(ret, "sample_comm_ao_register");
|
||||
|
||||
ret = sample_comm_ao_start(&g_ao_config);
|
||||
CHECK_RET(ret, "sample_comm_ao_start");
|
||||
|
||||
vol = 10;
|
||||
ret = sample_comm_ao_set_volume(&g_ao_config, vol);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
uac_logw("Set ao volume %d return 0x%x.\n", vol, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_stop_ao(xmedia_void)
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = sample_comm_ao_stop(&g_ao_config);
|
||||
CHECK_RET(ret, "sample_comm_ao_stop");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int get_sample_bytes(void)
|
||||
{
|
||||
switch (g_ao_args.format) {
|
||||
case AUDIO_BIT_DEPTH_8:
|
||||
return 1;
|
||||
|
||||
case AUDIO_BIT_DEPTH_16:
|
||||
return 2;
|
||||
|
||||
case AUDIO_BIT_DEPTH_24:
|
||||
return 3;
|
||||
|
||||
case AUDIO_BIT_DEPTH_32:
|
||||
return 4;
|
||||
|
||||
case AUDIO_BIT_DEPTH_UNKNOWN:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_send_frame_to_ao(char* buf, int size, int time_out)
|
||||
{
|
||||
int ret, i;
|
||||
audio_frame frame;
|
||||
xmedia_u32 send_size;
|
||||
unsigned int period_time = g_ao_args.period_time;
|
||||
unsigned int sample_bytes = get_sample_bytes();
|
||||
|
||||
frame.bit_depth = g_ao_config.frame_info.frm_bit;
|
||||
frame.channels = g_ao_config.frame_info.frm_chn;
|
||||
frame.interleaved = g_ao_args.is_interleaved;
|
||||
frame.sample_rate = g_ao_config.frame_info.frm_rate;
|
||||
frame.timestamp = -1;
|
||||
|
||||
// frame.sample_rate / 1000 : Number of samples per millisecond
|
||||
// period_time : Milliseconds of one cycle
|
||||
// frame.channels * sample_bytes : The byte size of a sample.
|
||||
send_size = (frame.sample_rate / 1000) * (frame.channels * sample_bytes) * period_time;
|
||||
|
||||
frame.data = (xmedia_void*)buf;
|
||||
frame.size = MIN(send_size, size);
|
||||
|
||||
if (send_size != size) {
|
||||
uac_logw("send_size(%d) != buf.size(%d).\n", send_size, size);
|
||||
}
|
||||
|
||||
for (i = 0; i < g_ao_config.dev_attr.channels; i++) {
|
||||
ret = xmedia_ao_send_frame(g_ao_config.dev, i, &frame, time_out);
|
||||
if (ret != XMEDIA_SUCCESS) {
|
||||
uac_loge("xmedia_ao_send_frame failed, error=%d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xmedia_s32 comm_audio_init()
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = xmedia_ai_init();
|
||||
CHECK_RET(ret, "xmedia_ai_init");
|
||||
|
||||
ret = xmedia_ao_init();
|
||||
CHECK_RET(ret, "xmedia_ao_init");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 comm_audio_exit()
|
||||
{
|
||||
xmedia_s32 ret;
|
||||
|
||||
ret = xmedia_ai_exit();
|
||||
CHECK_RET(ret, "xmedia_ai_exit");
|
||||
|
||||
ret = xmedia_ao_exit();
|
||||
CHECK_RET(ret, "xmedia_ao_exit");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_init_audio(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
sample_audio_lock();
|
||||
if (g_audio_init) {
|
||||
g_audio_init++;
|
||||
sample_audio_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = comm_audio_init();
|
||||
if (err < 0) {
|
||||
uac_loge("sample_comm_audio_init failed.\n");
|
||||
sample_audio_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
g_audio_init++;
|
||||
sample_audio_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xmedia_s32 sample_deinit_audio(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
sample_audio_lock();
|
||||
if (!g_audio_init) {
|
||||
sample_audio_unlock();
|
||||
return 0;
|
||||
} else {
|
||||
g_audio_init--;
|
||||
}
|
||||
|
||||
if (g_audio_init == 0) {
|
||||
err = comm_audio_exit();
|
||||
if (err < 0) {
|
||||
uac_loge("comm_audio_exit failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
sample_audio_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int sample_audio_ai_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
unsigned int format,
|
||||
bool is_interleaved)
|
||||
{
|
||||
g_ai_args.channels = channels;
|
||||
g_ai_args.sample_rate = rate;
|
||||
g_ai_args.period_time = period_time;
|
||||
g_ai_args.format = format;
|
||||
g_ai_args.is_interleaved = is_interleaved;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_ai_startup(void)
|
||||
{
|
||||
if (sample_init_audio() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sample_start_ai() < 0) {
|
||||
sample_deinit_audio();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_ai_shutdown(void)
|
||||
{
|
||||
sample_stop_ai();
|
||||
|
||||
sample_deinit_audio();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_get_frame_from_ai(char* buf, int size, int time_out)
|
||||
{
|
||||
if (buf == NULL || size <= 0) {
|
||||
uac_loge("Invalid param.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sample_recv_frame_from_ai(buf, size, time_out);
|
||||
}
|
||||
|
||||
int sample_audio_ao_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
unsigned int format,
|
||||
bool is_interleaved)
|
||||
{
|
||||
g_ao_args.channels = channels;
|
||||
g_ao_args.sample_rate = rate;
|
||||
g_ao_args.period_time = period_time;
|
||||
g_ao_args.format = format;
|
||||
g_ao_args.is_interleaved = is_interleaved;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_ao_startup(void)
|
||||
{
|
||||
if (sample_init_audio() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sample_start_ao() < 0) {
|
||||
sample_deinit_audio();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_ao_shutdown(void)
|
||||
{
|
||||
sample_stop_ao();
|
||||
|
||||
sample_deinit_audio();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sample_audio_send_frame_to_ao(char* buf, int size, int time_out)
|
||||
{
|
||||
if (buf == NULL || size <= 0) {
|
||||
uac_loge("Invlaid params.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sample_send_frame_to_ao(buf, size, time_out);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __SAMPLE_AUDIO_H__
|
||||
#define __SAMPLE_AUDIO_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "xmedia_audio_common.h"
|
||||
|
||||
int sample_audio_ai_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_bit_depth format,
|
||||
bool is_interleaved);
|
||||
int sample_audio_ai_startup(void);
|
||||
int sample_audio_ai_shutdown(void);
|
||||
int sample_audio_get_frame_from_ai(char* buf, int size, int time_out);
|
||||
|
||||
int sample_audio_ao_config(unsigned int channels,
|
||||
unsigned int rate,
|
||||
unsigned int period_time,
|
||||
audio_bit_depth format,
|
||||
bool is_interleaved);
|
||||
int sample_audio_ao_startup(void);
|
||||
int sample_audio_ao_shutdown(void);
|
||||
int sample_audio_send_frame_to_ao(char* buf, int size, int time_out);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "uac.h"
|
||||
#include "uac_hal.h"
|
||||
#include "audio_stream.h"
|
||||
|
||||
#include "uac_log.h"
|
||||
|
||||
static uac_dev_t* uac_dev = NULL;
|
||||
|
||||
static int __uac_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
audio_stream_operate_t* audio_stream = NULL;
|
||||
|
||||
audio_stream = get_audio_stream();
|
||||
if (audio_stream == NULL) {
|
||||
uac_loge("Create audio stream dev failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uac_dev = get_uac_dev();
|
||||
if (uac_dev == NULL) {
|
||||
uac_loge("Careate uac dev failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = uac_stream_register(audio_stream);
|
||||
if (err < 0) {
|
||||
uac_loge("UAC register stream dev failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uac_dev->init) {
|
||||
err = uac_dev->init();
|
||||
} else {
|
||||
err = -1;
|
||||
uac_loge("Invalid uac_dev.\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __uac_deinit(void)
|
||||
{
|
||||
if (uac_dev && uac_dev->deinit) {
|
||||
uac_dev->deinit();
|
||||
uac_stream_unregister();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __uac_open(void)
|
||||
{
|
||||
if (uac_dev && uac_dev->open) {
|
||||
return uac_dev->open();
|
||||
} else {
|
||||
uac_loge("Invalid uac_dev.\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __uac_close(void)
|
||||
{
|
||||
if (uac_dev && uac_dev->close) {
|
||||
return uac_dev->close();
|
||||
} else {
|
||||
uac_loge("Invalid uac_dev.\n");
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __uac_run(void)
|
||||
{
|
||||
if (uac_dev && uac_dev->run) {
|
||||
return uac_dev->run();
|
||||
} else {
|
||||
uac_loge("Invalid uac_dev.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uac_stop(void)
|
||||
{
|
||||
if (uac_dev && uac_dev->stop) {
|
||||
return uac_dev->stop();
|
||||
} else {
|
||||
uac_loge("Invalid uac_dev.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static uac_t __uac = {
|
||||
.init = &__uac_init,
|
||||
.deinit = &__uac_deinit,
|
||||
.open = &__uac_open,
|
||||
.close = &__uac_close,
|
||||
.run = &__uac_run,
|
||||
.stop = &__uac_stop,
|
||||
};
|
||||
|
||||
uac_t *get_uac(void)
|
||||
{
|
||||
return &__uac;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#ifndef __UAC_LOG_H__
|
||||
#define __UAC_LOG_H__
|
||||
|
||||
#include "log_base.h"
|
||||
|
||||
#undef TAG
|
||||
#define TAG "UAC"
|
||||
|
||||
#define uac_loge LOGE
|
||||
#define uac_logw LOGW
|
||||
#define uac_logi LOGI
|
||||
#define uac_logt LOGT
|
||||
#define uac_logd LOGD
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user