578 lines
17 KiB
C
Executable File
578 lines
17 KiB
C
Executable File
/*
|
|
* Copyright (c) 2008-2017 Allwinner Technology Co. Ltd.
|
|
* All rights reserved.
|
|
*
|
|
* File : tinyplaydemo.c
|
|
* Description : demoAdecoder
|
|
* History :
|
|
*
|
|
*/
|
|
|
|
#include "tinyplaydemo.h"
|
|
#include "demo_utils.h"
|
|
#include <fcntl.h>
|
|
|
|
#ifdef LOG_TAG
|
|
#undef LOG_TAG
|
|
#define LOG_TAG "Tinyplaydemo"
|
|
#endif
|
|
#define DEMO_DEBUG 1
|
|
|
|
#define ID_RIFF 0x46464952
|
|
#define ID_WAVE 0x45564157
|
|
#define ID_FMT 0x20746d66
|
|
#define ID_DATA 0x61746164
|
|
|
|
typedef struct name_map_t
|
|
{
|
|
char name_linux[32];
|
|
char name_android[32];
|
|
}name_map;
|
|
|
|
#define AUDIO_MAP_CNT 16
|
|
#define AUDIO_NAME_CODEC "AUDIO_CODEC"
|
|
#define AUDIO_NAME_HDMI "AUDIO_HDMI"
|
|
#define AUDIO_NAME_SPDIF "AUDIO_SPDIF"
|
|
#define AUDIO_NAME_I2S "AUDIO_I2S"
|
|
#define AUDIO_NAME_RT3261 "AUDIO_CODEC_RT"
|
|
#define AUDIO_NAME_RT3261_RAW "RT3261_RAW"
|
|
#define AUDIO_NAME_MIX "AUDIO_MIX"
|
|
#define AUDIO_NAME_BT "AUDIO_BT"
|
|
|
|
static name_map audio_name_map[AUDIO_MAP_CNT] =
|
|
{
|
|
{"snddaudio", AUDIO_NAME_CODEC},//A80
|
|
{"audiocodec", AUDIO_NAME_CODEC},//A31,A20
|
|
{"sndacx00codec", AUDIO_NAME_CODEC},//H6
|
|
{"sndhdmi", AUDIO_NAME_HDMI},
|
|
{"rt3261aif2", AUDIO_NAME_RT3261_RAW},
|
|
{"sndspdif", AUDIO_NAME_SPDIF},
|
|
{"rt3261", AUDIO_NAME_RT3261},
|
|
{"snddaudio2", AUDIO_NAME_BT},
|
|
{"sndahub", AUDIO_NAME_MIX},
|
|
};
|
|
|
|
enum SND_AUIDO_RAW_DATA_TYPE
|
|
{
|
|
SND_AUDIO_RAW_DATA_UNKOWN = 0,
|
|
SND_AUDIO_RAW_DATA_PCM = 1,
|
|
SND_AUDIO_RAW_DATA_AC3 = 2,
|
|
SND_AUDIO_RAW_DATA_MPEG1 = 3,
|
|
SND_AUDIO_RAW_DATA_MP3 = 4,
|
|
SND_AUDIO_RAW_DATA_MPEG2 = 5,
|
|
SND_AUDIO_RAW_DATA_AAC = 6,
|
|
SND_AUDIO_RAW_DATA_DTS = 7,
|
|
SND_AUDIO_RAW_DATA_ATRAC = 8,
|
|
SND_AUDIO_RAW_DATA_ONE_BIT_AUDIO = 9,
|
|
SND_AUDIO_RAW_DATA_DOLBY_DIGITAL_PLUS = 10,
|
|
SND_AUDIO_RAW_DATA_DTS_HD = 11,
|
|
SND_AUDIO_RAW_DATA_MAT = 12,
|
|
SND_AUDIO_RAW_DATA_DST = 13,
|
|
SND_AUDIO_RAW_DATA_WMAPRO = 14
|
|
};
|
|
|
|
struct riff_wave_header {
|
|
uint32_t riff_id;
|
|
uint32_t riff_sz;
|
|
uint32_t wave_id;
|
|
};
|
|
|
|
struct chunk_header {
|
|
uint32_t id;
|
|
uint32_t sz;
|
|
};
|
|
|
|
struct chunk_fmt {
|
|
uint16_t audio_format;
|
|
uint16_t num_channels;
|
|
uint32_t sample_rate;
|
|
uint32_t byte_rate;
|
|
uint16_t block_align;
|
|
uint16_t bits_per_sample;
|
|
};
|
|
|
|
static int find_name_map(AudioDsp *adev, char * in, char * out)
|
|
{
|
|
int index = 0;
|
|
CDX_UNUSE(adev);
|
|
if (in == 0 || out == 0)
|
|
{
|
|
demo_loge("error params");
|
|
return -1;
|
|
}
|
|
|
|
for (; index < AUDIO_MAP_CNT; index++)
|
|
{
|
|
if (strlen(audio_name_map[index].name_linux) == 0)
|
|
{
|
|
|
|
//sprintf(out, "AUDIO_USB%d", adev->usb_audio_cnt++);
|
|
sprintf(out, "AUDIO_USB_%s", in);
|
|
strcpy(audio_name_map[index].name_linux, in);
|
|
strcpy(audio_name_map[index].name_android, out);
|
|
demo_logd("linux name = %s, android name = %s",
|
|
audio_name_map[index].name_linux,
|
|
audio_name_map[index].name_android);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(in, audio_name_map[index].name_linux))
|
|
{
|
|
strcpy(out, audio_name_map[index].name_android);
|
|
demo_logd("linux name = %s, android name = %s",
|
|
audio_name_map[index].name_linux,
|
|
audio_name_map[index].name_android);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int do_init_audio_card(AudioDsp *adev, int card)
|
|
{
|
|
int ret = -1;
|
|
int fd = 0;
|
|
char * snd_path = "/sys/class/sound";
|
|
char snd_card[128], snd_node[128];
|
|
char snd_id[32], snd_name[32];
|
|
|
|
memset(snd_card, 0, sizeof(snd_card));
|
|
memset(snd_node, 0, sizeof(snd_node));
|
|
memset(snd_id, 0, sizeof(snd_id));
|
|
memset(snd_name, 0, sizeof(snd_name));
|
|
|
|
sprintf(snd_card, "%s/card%d", snd_path, card);
|
|
ret = access(snd_card, F_OK);
|
|
if(ret == 0)
|
|
{
|
|
// id / name
|
|
sprintf(snd_node, "%s/card%d/id", snd_path, card);
|
|
demo_logd("1... read card %s/card%d/id",snd_path, card);
|
|
fd = open(snd_node, O_RDONLY);
|
|
if (fd > 0)
|
|
{
|
|
ret = read(fd, snd_id, sizeof(snd_id));
|
|
if (ret > 0)
|
|
{
|
|
snd_id[ret - 1] = '\0';
|
|
demo_logd("2.... %s, %s, card: %d", snd_node, snd_id, card);
|
|
}
|
|
close(fd);
|
|
}
|
|
else
|
|
{
|
|
demo_logd("3.... fd fail ....%s, %s, len: %d", snd_node, snd_id, card);
|
|
return -1;
|
|
}
|
|
strcpy(adev->dev_manager[card].card_id, snd_id);
|
|
find_name_map(adev, snd_id, snd_name);
|
|
strcpy(adev->dev_manager[card].name, snd_name);
|
|
|
|
adev->dev_manager[card].card = card;
|
|
adev->dev_manager[card].device = 0;
|
|
adev->dev_manager[card].flag_exist = true;
|
|
|
|
// playback device
|
|
sprintf(snd_node, "%s/card%d/pcmC%dD0p", snd_path, card, card);
|
|
ret = access(snd_node, F_OK);
|
|
if(ret == 0)
|
|
{
|
|
// there is a playback device
|
|
adev->dev_manager[card].flag_out = AUDIO_OUT;
|
|
adev->dev_manager[card].flag_out_active = 0;
|
|
}
|
|
|
|
// capture device
|
|
sprintf(snd_node, "%s/card%d/pcmC%dD0c", snd_path, card, card);
|
|
ret = access(snd_node, F_OK);
|
|
if(ret == 0)
|
|
{
|
|
// there is a capture device
|
|
adev->dev_manager[card].flag_in = AUDIO_IN;
|
|
adev->dev_manager[card].flag_in_active = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void init_audio_devices(AudioDsp *adev)
|
|
{
|
|
int card = 0;
|
|
|
|
memset(adev->dev_manager, 0, sizeof(adev->dev_manager));
|
|
|
|
for (card = 0; card < MAX_AUDIO_DEVICES; card++)
|
|
{
|
|
if (do_init_audio_card(adev, card) == 0)
|
|
{
|
|
// break;
|
|
demo_logd("card: %d, name: %s, capture: %d, playback: %d",
|
|
card, adev->dev_manager[card].name,
|
|
adev->dev_manager[card].flag_in == AUDIO_IN,
|
|
adev->dev_manager[card].flag_out == AUDIO_OUT);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void getCardNumbyName(AudioDsp *adev, char *name, int *card)
|
|
{
|
|
int index;
|
|
for (index = 0; index < MAX_AUDIO_DEVICES; index++) {
|
|
if (!strcmp(adev->dev_manager[index].name, name)) {
|
|
*card = index;
|
|
demo_logd("getCardNumbyName: name = %s , card = %d",name, index);
|
|
demo_logd("NAME = %s",adev->dev_manager[index].name);
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (index = 0; index < MAX_AUDIO_DEVICES; index++) {
|
|
if (!strncmp(adev->dev_manager[index].name, "AUDIO_USB", 9)
|
|
&& !strncmp(name, "AUDIO_USB", 9)
|
|
&& adev->dev_manager[index].flag_exist) {
|
|
*card = index;
|
|
demo_logd("USBNAME = %s",adev->dev_manager[index].name);
|
|
demo_logd("getCardNumbyName: name = %s , card = %d",name, index);
|
|
break;
|
|
}
|
|
}
|
|
demo_logd("card 0 name = %s",adev->dev_manager[0].name);
|
|
if (index == MAX_AUDIO_DEVICES) {
|
|
demo_logd("BT");
|
|
*card = -1;
|
|
demo_loge("%s card does not exist",name);
|
|
}
|
|
}
|
|
|
|
#ifdef H6_AUDIO_HUB
|
|
void enble_hub_hdmi(struct mixer *mixer)
|
|
{
|
|
demo_logd("enble_hub_hdmi");
|
|
struct mixer_ctl *ctl;
|
|
//i2s1->APBIF_TXDIF0
|
|
ctl = mixer_get_ctl_by_name(mixer, "I2S1 Src Select");
|
|
mixer_ctl_set_value(ctl, 0, 1);
|
|
//enble i2s1
|
|
ctl = mixer_get_ctl_by_name(mixer, "I2S1OUT Switch");
|
|
mixer_ctl_set_value(ctl, 0, 1);
|
|
}
|
|
void close_hub_hdmi(struct mixer *mixer)
|
|
{
|
|
demo_logd("close_hub_hdmi");
|
|
struct mixer_ctl *ctl;
|
|
//i2s1->APBIF_TXDIF0
|
|
ctl = mixer_get_ctl_by_name(mixer, "I2S1 Src Select");
|
|
mixer_ctl_set_value(ctl, 0, 0);
|
|
//close i2s1
|
|
ctl = mixer_get_ctl_by_name(mixer, "I2S1OUT Switch");
|
|
mixer_ctl_set_value(ctl, 0, 0);
|
|
}
|
|
|
|
static int set_ahub_rontiue(int ahub_card_id, const char* name, int on_off)
|
|
{
|
|
struct mixer *audio_hub_mixer = mixer_open(ahub_card_id);
|
|
if(!audio_hub_mixer)
|
|
{
|
|
demo_loge("Unable to open the audio_hub_mixer, aborting...");
|
|
return -1;
|
|
}
|
|
//Now only fix the HDMI scenoris
|
|
if(on_off != 0)//enable...
|
|
{
|
|
if(!strcmp(name, AUDIO_NAME_HDMI))
|
|
{
|
|
demo_logi("ahub enable hdmi hub...");
|
|
enble_hub_hdmi(audio_hub_mixer);
|
|
}
|
|
}
|
|
else//shut down...
|
|
{
|
|
if(!strcmp(name, AUDIO_NAME_HDMI))
|
|
{
|
|
demo_logi("ahub shut down hdmi hub...");
|
|
close_hub_hdmi(audio_hub_mixer);
|
|
}
|
|
}
|
|
|
|
mixer_close(audio_hub_mixer);
|
|
audio_hub_mixer = NULL;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int set_raw_flag(AudioDsp* dsp, int card, int raw_flag)
|
|
{
|
|
demo_logi("set_raw_flag(card=%d, raw_flag=%d)", card, raw_flag);
|
|
struct mixer *mixer = mixer_open(card);
|
|
if (!mixer) {
|
|
demo_loge("Unable to open the mixer, aborting...");
|
|
return -1;
|
|
}
|
|
const char *control_name = (card == dsp->cardHDMI) ? "hdmi audio format Function":
|
|
(card == dsp->cardMIX) ? "ahub audio format Function":
|
|
"spdif audio format Function";
|
|
demo_logi("control_name : %s, card : %d", control_name, card);
|
|
const char *control_value = (raw_flag==SND_AUDIO_RAW_DATA_AC3) ? "AC3" :
|
|
(raw_flag==SND_AUDIO_RAW_DATA_DOLBY_DIGITAL_PLUS) ? "DOLBY_DIGITAL_PLUS":
|
|
(raw_flag==SND_AUDIO_RAW_DATA_MAT) ? "MAT":
|
|
(raw_flag==SND_AUDIO_RAW_DATA_DTS) ? "DTS" : "pcm";
|
|
struct mixer_ctl *audio_format = mixer_get_ctl_by_name(mixer, control_name);
|
|
if (audio_format)
|
|
mixer_ctl_set_enum_by_string(audio_format, control_value);
|
|
mixer_close(mixer);
|
|
return 0;
|
|
}
|
|
|
|
int check_param(struct pcm_params *params, unsigned int param, unsigned int value,
|
|
char *param_name, char *param_unit)
|
|
{
|
|
unsigned int min;
|
|
unsigned int max;
|
|
int is_within_bounds = 1;
|
|
|
|
min = pcm_params_get_min(params, param);
|
|
if (value < min) {
|
|
demo_loge("%s is %u%s, device only supports >= %u%s", param_name, value,
|
|
param_unit, min, param_unit);
|
|
is_within_bounds = 0;
|
|
}
|
|
|
|
max = pcm_params_get_max(params, param);
|
|
if (value > max) {
|
|
demo_loge("%s is %u%s, device only supports <= %u%s", param_name, value,
|
|
param_unit, max, param_unit);
|
|
is_within_bounds = 0;
|
|
}
|
|
|
|
return is_within_bounds;
|
|
}
|
|
|
|
static int sample_is_playable(unsigned int card, unsigned int device, unsigned int channels,
|
|
unsigned int rate, unsigned int bits, unsigned int period_size,
|
|
unsigned int period_count)
|
|
{
|
|
struct pcm_params *params;
|
|
int can_play;
|
|
demo_loge("line : %d, card:%u, device:%u",__LINE__, card, device);
|
|
params = pcm_params_get(card, device, PCM_OUT);
|
|
if (params == NULL) {
|
|
demo_loge("Unable to open PCM device %u", device);
|
|
return 0;
|
|
}
|
|
demo_loge("line : %d, card:%u, device:%u",__LINE__, card, device);
|
|
|
|
can_play = check_param(params, PCM_PARAM_RATE, rate, "Sample rate", "Hz");
|
|
can_play &= check_param(params, PCM_PARAM_CHANNELS, channels, "Sample", " channels");
|
|
can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, bits, "Bitrate", " bits");
|
|
can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, period_size, "Period size", "Hz");
|
|
can_play &= check_param(params, PCM_PARAM_PERIODS, period_count, "Period count", "Hz");
|
|
|
|
pcm_params_free(params);
|
|
|
|
return can_play;
|
|
}
|
|
|
|
int DspWrite(AudioDsp* dsp, void *pPcmData, int nPcmDataLen)
|
|
{
|
|
void* buf_conv = NULL;
|
|
int buf_conv_len = 0;
|
|
int samples = 0;
|
|
|
|
if(!dsp)
|
|
return -1;
|
|
|
|
if(!dsp->start)
|
|
{
|
|
dsp->config.channels = dsp->ch;
|
|
dsp->config.rate = dsp->spr;
|
|
dsp->config.period_size = dsp->period_size;
|
|
dsp->config.period_count = dsp->period_count;
|
|
dsp->config.raw_flag = dsp->raw_flag;
|
|
if (dsp->bps == 32)
|
|
dsp->config.format = PCM_FORMAT_S32_LE;
|
|
else if (dsp->bps == 24)
|
|
dsp->config.format = PCM_FORMAT_S24_LE;
|
|
else
|
|
dsp->config.format = PCM_FORMAT_S16_LE;
|
|
|
|
demo_logi("dsp->bps : %d", dsp->bps);
|
|
dsp->config.start_threshold = 0;
|
|
dsp->config.stop_threshold = 0;
|
|
dsp->config.silence_threshold = 0;
|
|
|
|
if(set_raw_flag(dsp, dsp->cardHDMI, dsp->raw_flag) < 0){
|
|
demo_loge("can not set raw flag...");
|
|
return -1;
|
|
}
|
|
demo_logi("hdmi , raw_flag : %d, ch : %d, spr : %d, period_size : %d, period_count : %d",
|
|
dsp->config.raw_flag, dsp->config.channels , dsp->config.rate, dsp->config.period_size,
|
|
dsp->config.period_count);
|
|
|
|
#ifdef H6_AUDIO_HUB
|
|
dsp->hubconfig = dsp->config;
|
|
|
|
if(set_raw_flag(dsp, dsp->cardMIX, dsp->raw_flag) < 0){
|
|
demo_loge("can not set raw flag...");
|
|
return -1;
|
|
}
|
|
demo_logi("ahub , raw_flag : %d, ch : %d, spr : %d, period_size : %d, period_count : %d",
|
|
dsp->hubconfig.raw_flag, dsp->hubconfig.channels , dsp->hubconfig.rate,
|
|
dsp->hubconfig.period_size, dsp->hubconfig.period_count);
|
|
|
|
set_ahub_rontiue(dsp->cardMIX, AUDIO_NAME_HDMI, 1);
|
|
|
|
dsp->pcmhub = pcm_open(dsp->cardMIX, dsp->device, PCM_OUT, &dsp->hubconfig);
|
|
if (!dsp->pcmhub || !pcm_is_ready(dsp->pcmhub)) {
|
|
demo_loge("Unable to open PCM device %d (%s)\n",
|
|
dsp->device, pcm_get_error(dsp->pcmhub));
|
|
return -1;
|
|
}
|
|
#else
|
|
dsp->pcm = pcm_open(dsp->cardHDMI, dsp->device, PCM_OUT, &dsp->config);
|
|
if (!dsp->pcm || !pcm_is_ready(dsp->pcm)) {
|
|
demo_loge("Unable to open PCM device %u (%s)\n",
|
|
dsp->device, pcm_get_error(dsp->pcm));
|
|
return -1;
|
|
}
|
|
#endif
|
|
dsp->start = 1;
|
|
}
|
|
|
|
if(nPcmDataLen > 0)
|
|
{
|
|
if (dsp->bps == 24)
|
|
{
|
|
int idx = 0, jdx = 0;
|
|
char* dst = NULL;
|
|
char* src = NULL;
|
|
samples = nPcmDataLen * 8/ dsp->ch / dsp->bps;
|
|
buf_conv_len = nPcmDataLen*4/3;
|
|
|
|
DEMO_VERBOS_SAFE_MALLOC(buf_conv, buf_conv_len,
|
|
demo_loge("Error no mem for conventer buffer...");\
|
|
return -1;
|
|
)
|
|
|
|
dst = (char*)buf_conv;
|
|
for(idx = 0; idx < dsp->ch; idx++)
|
|
{
|
|
dst = ((char*)buf_conv) + 4*idx;
|
|
src = ((char*)pPcmData) + 3*idx;
|
|
for(jdx = 0; jdx < samples; jdx++){
|
|
dst[0] = src[0]&0xff;
|
|
dst[1] = src[1]&0xff;
|
|
dst[2] = src[2]&0xff;
|
|
dst[3] = (dst[2]&0x80)?0xff:0x00;
|
|
dst += 4*dsp->ch;
|
|
src += 3*dsp->ch;
|
|
}
|
|
}
|
|
#ifdef H6_AUDIO_HUB
|
|
if (pcm_write(dsp->pcmhub, buf_conv, buf_conv_len) < 0)
|
|
#else
|
|
if (pcm_write(dsp->pcm, buf_conv, buf_conv_len) < 0)
|
|
#endif
|
|
{
|
|
demo_loge("Error playing sample...");
|
|
DEMO_SAFE_FREE(buf_conv, "buf_conv", 0)
|
|
return -1;
|
|
}
|
|
DEMO_SAFE_FREE(buf_conv, "buf_conv", 0)
|
|
}
|
|
else
|
|
{
|
|
#ifdef H6_AUDIO_HUB
|
|
if (pcm_write(dsp->pcmhub, pPcmData, nPcmDataLen) < 0)
|
|
#else
|
|
if (pcm_write(dsp->pcm, pPcmData, nPcmDataLen) < 0)
|
|
#endif
|
|
{
|
|
demo_loge("Error playing sample...");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
demo_loge("Invaild write len : %d", nPcmDataLen);
|
|
return nPcmDataLen;
|
|
}
|
|
|
|
int DspStop(AudioDsp* dsp)
|
|
{
|
|
if(!dsp)
|
|
return -1;
|
|
|
|
if(dsp->start)
|
|
{
|
|
#ifdef H6_AUDIO_HUB
|
|
if(dsp->pcmhub)
|
|
{
|
|
pcm_close(dsp->pcmhub);
|
|
dsp->pcmhub = NULL;
|
|
set_ahub_rontiue(dsp->cardMIX, AUDIO_NAME_HDMI, 0);
|
|
demo_logi("Dsp pcmhub device closed ...");
|
|
}
|
|
#else
|
|
if(dsp->pcm)
|
|
{
|
|
pcm_close(dsp->pcm);
|
|
dsp->pcm = NULL;
|
|
demo_logi("Dsp pcm device closed ...");
|
|
}
|
|
#endif
|
|
dsp->start = 0;
|
|
}
|
|
else
|
|
{
|
|
demo_logd("dsp stop while unactive...");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void DspWaitForDevConsume(int waitms)
|
|
{
|
|
usleep(waitms * 1000);
|
|
}
|
|
|
|
extern void NotifyHalDirect(int on_off);
|
|
|
|
AudioDsp* CreateAudioDsp()
|
|
{
|
|
AudioDsp* pMem = NULL;
|
|
DEMO_VERBOS_SAFE_MALLOC(pMem, sizeof(AudioDsp),
|
|
demo_loge("CreateAudioDsp fail for no mem...");\
|
|
return NULL;
|
|
);
|
|
NotifyHalDirect(1);
|
|
init_audio_devices(pMem);
|
|
getCardNumbyName(pMem, AUDIO_NAME_CODEC, &pMem->cardCODEC);
|
|
getCardNumbyName(pMem, AUDIO_NAME_HDMI, &pMem->cardHDMI);
|
|
getCardNumbyName(pMem, AUDIO_NAME_SPDIF, &pMem->cardSPDIF);
|
|
getCardNumbyName(pMem, AUDIO_NAME_BT, &pMem->cardBT);
|
|
getCardNumbyName(pMem, AUDIO_NAME_MIX, &pMem->cardMIX);
|
|
demo_logi("cardCODEC : %d, cardHDMI: %d, cardSPDIF: %d, cardBT: %d, cardMIX: %d",
|
|
pMem->cardCODEC, pMem->cardHDMI, pMem->cardSPDIF, pMem->cardBT, pMem->cardMIX);
|
|
return pMem;
|
|
}
|
|
|
|
void DeleteAudioDsp(AudioDsp* dsp)
|
|
{
|
|
AudioDsp* pMem = NULL;
|
|
pMem = dsp;
|
|
|
|
if(!pMem)
|
|
{
|
|
demo_loge("DeleteAudioDsp strange for null ptr...");
|
|
return;
|
|
}
|
|
DspStop(pMem);
|
|
NotifyHalDirect(0);
|
|
DEMO_SAFE_FREE(pMem, "AudioDsp", 1)
|
|
}
|