524 lines
18 KiB
C
524 lines
18 KiB
C
/*
|
|
* Copyright 2020-2021 NXP
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#ifdef EAP_PROC
|
|
|
|
#include "osa_types.h"
|
|
#include "osa_memory.h"
|
|
#include "fsl_debug_console.h"
|
|
|
|
#include "streamer_api.h"
|
|
#include "streamer_element_properties.h"
|
|
|
|
#include "app_streamer.h"
|
|
#include "eap_proc.h"
|
|
#include "eap_att.h"
|
|
#include "app_data.h"
|
|
|
|
#include "EAP_Parameter_AllEffectOff.h"
|
|
#include "EAP_Parameter_AutoVolumeLeveler.h"
|
|
#if (ALGORITHM_CS == 1)
|
|
#include "EAP_Parameter_ConcertSound.h"
|
|
#endif
|
|
#if (ALGORITHM_XO == 1)
|
|
#include "EAP_Parameter_Crossover2waySpeakers.h"
|
|
#include "EAP_Parameter_CrossoverForSubwoofer.h"
|
|
#endif
|
|
|
|
#include "EAP_Parameter_ToneGenerator.h"
|
|
#include "EAP_Parameter_LoudnessMaximiser.h"
|
|
|
|
#ifdef CPU_LPC55S69JBD100_cm33_core0
|
|
#include "EAP_Parameter_MusicEnhancerRMSLimiter_lowMIPS.h"
|
|
#include "EAP_Parameter_VoiceEnhancer_lowMIPS.h"
|
|
#else
|
|
#include "EAP_Parameter_MusicEnhancerRMSLimiter.h"
|
|
#include "EAP_Parameter_VoiceEnhancer.h"
|
|
#include "EAP_Parameter_Custom.h"
|
|
#endif
|
|
|
|
// EAP Lib
|
|
static LVM_Handle_t EAP_hInstance; /* Instance handle */
|
|
typedef struct _eap_preset_t
|
|
{
|
|
char *name;
|
|
LVM_ControlParams_t *controlParams;
|
|
LVM_InstParams_t *instParams;
|
|
LVM_HeadroomParams_t *headroomParams;
|
|
} eap_preset_t;
|
|
|
|
eap_preset_t eap_presets[] = {{.name = "AllEffectOff",
|
|
.controlParams = &ControlParamSet_allEffectOff,
|
|
.instParams = &InstParams_allEffectOff,
|
|
.headroomParams = &HeadroomParams_allEffectOff},
|
|
{.name = "VoiceEnhancer",
|
|
#ifdef CPU_LPC55S69JBD100_cm33_core0
|
|
.controlParams = &ControlParamSet_voiceEnhancer_lowMIPS,
|
|
.instParams = &InstParams_voiceEnhancer_lowMIPS,
|
|
.headroomParams = &HeadroomParams_voiceEnhancer_lowMIPS},
|
|
#else
|
|
.controlParams = &ControlParamSet_voiceEnhancer,
|
|
.instParams = &InstParams_voiceEnhancer,
|
|
.headroomParams = &HeadroomParams_voiceEnhancer},
|
|
#endif
|
|
{.name = "MusicEnhancer",
|
|
#ifdef CPU_LPC55S69JBD100_cm33_core0
|
|
.controlParams = &ControlParamSet_musicEnhancerRmsLimiter_lowMIPS,
|
|
.instParams = &InstParams_musicEnhancerRmsLimiter_lowMIPS,
|
|
.headroomParams = &HeadroomParams_musicEnhancerRmsLimiter_lowMIPS},
|
|
#else
|
|
.controlParams = &ControlParamSet_musicEnhancerRmsLimiter,
|
|
.instParams = &InstParams_musicEnhancerRmsLimiter,
|
|
.headroomParams = &HeadroomParams_musicEnhancerRmsLimiter},
|
|
#endif
|
|
{.name = "AutoVolumeLeveler",
|
|
.controlParams = &ControlParamSet_autoVolumeLeveler,
|
|
.instParams = &InstParams_autoVolumeLeveler,
|
|
.headroomParams = &HeadroomParams_autoVolumeLeveler},
|
|
{.name = "LoudnessMaximiser",
|
|
.controlParams = &ControlParamSet_loudnessMaximiser,
|
|
.instParams = &InstParams_loudnessMaximiser,
|
|
.headroomParams = &HeadroomParams_loudnessMaximiser},
|
|
#if (ALGORITHM_CS == 1)
|
|
{.name = "ConcertSound",
|
|
.controlParams = &ControlParamSet_concertSound,
|
|
.instParams = &InstParams_concertSound,
|
|
.headroomParams = &HeadroomParams_concertSound},
|
|
#endif
|
|
#ifndef CPU_LPC55S69JBD100_cm33_core0
|
|
{.name = "Custom",
|
|
.controlParams = &ControlParamSet_custom,
|
|
.instParams = &InstParams_custom,
|
|
.headroomParams = &HeadroomParams_custom},
|
|
#endif
|
|
{.name = "ToneGenerator",
|
|
.controlParams = &ControlParamSet_toneGenerator,
|
|
.instParams = &InstParams_toneGenerator,
|
|
.headroomParams = &HeadroomParams_toneGenerator},
|
|
#if (ALGORITHM_XO == 1)
|
|
{.name = "Crossover2WaySpeakers",
|
|
.controlParams = &ControlParamSet_Crossover2WaySpeaker,
|
|
.instParams = &InstParams_Crossover2WaySpeaker,
|
|
.headroomParams = &HeadroomParams_Crossover2WaySpeaker},
|
|
{.name = "CrossoverForSubwoofer",
|
|
.controlParams = &ControlParamSet_CrossoverForSubwoofer,
|
|
.instParams = &InstParams_CrossoverForSubwoofer,
|
|
.headroomParams = &HeadroomParams_CrossoverForSubwoofer}
|
|
#endif
|
|
};
|
|
|
|
LVM_ReturnStatus_en EAP_SetFSandChannels(ext_proc_args *args);
|
|
|
|
static bool first_exec;
|
|
static LVM_MemTab_t EAP_MemTab; /* Memory allocation table */
|
|
static LVM_VersionInfo_st EAP_VersionInfo; /* Version info structure */
|
|
#if (ALGORITHM_XO == 1)
|
|
static LVM_INT16 *eap_xo_out_buffer[2];
|
|
#endif
|
|
#ifdef ALGORITHM_AVL
|
|
static LVM_INT32 avlGain;
|
|
#endif
|
|
|
|
#ifdef ALGORITHM_PSA
|
|
LVM_INT16 EAP_PSA_Bands = 16;
|
|
LVM_UINT32 EAP_PSA_AudioTime1 = 0;
|
|
LVM_UINT32 EAP_PSA_DisplayTimeInc = 60;
|
|
LVM_UINT32 EAP_PSA_StartOffset = 200;
|
|
|
|
LVM_INT8 EAP_PSA_Data_Lock = 0;
|
|
LVM_INT8 EAP_PSA_CurrPeaks[LVM_PSA_MAX_NUMBANDS];
|
|
LVM_INT8 EAP_PSA_PastPeaks[LVM_PSA_MAX_NUMBANDS];
|
|
LVM_UINT16 EAP_PSA_BandFreq[LVM_PSA_MAX_NUMBANDS];
|
|
#endif
|
|
|
|
static LVM_UINT32 EAP_AudioTime = 0;
|
|
|
|
// malloc memory
|
|
static LVM_INT16 MallocAlign = 4; /* 4 byte Malloc alignment */
|
|
|
|
int EAP_Init(void *arg)
|
|
{
|
|
LVM_ReturnStatus_en LVM_Status; /* Function call status */
|
|
LVM_UINT16 i, minIdx; /* loop index */
|
|
LVM_INT32 temp32; /* temporary address */
|
|
LVM_INT16 j;
|
|
LVM_UINT16 order[LVM_NR_MEMORY_REGIONS];
|
|
|
|
/******************************************************************************
|
|
GET VERSION INFORMATION
|
|
*******************************************************************************/
|
|
LVM_Status = LVM_GetVersionInfo(&EAP_VersionInfo);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
|
|
/******************************************************************************
|
|
SET THE INPUT PARAMETERS
|
|
*******************************************************************************/
|
|
/*
|
|
* Select parameter configuration
|
|
*/
|
|
ext_proc_args *args = arg;
|
|
eap_att_control_t *control = get_eap_att_control();
|
|
int presetIndex = get_app_data()->lastPreset;
|
|
if (presetIndex > 0)
|
|
{
|
|
presetIndex -= 1; // normalize ID to index, ID=0 is reserved for no-preset reload
|
|
if ((presetIndex < (sizeof(eap_presets) / sizeof(eap_presets[0]))))
|
|
{
|
|
eap_preset_t *preset = &(eap_presets[presetIndex]);
|
|
PRINTF("[EAP_STREAMER] loading preset %s\r\n", preset->name);
|
|
|
|
#ifdef ALGORITHM_EQNB
|
|
void *eqnbPtrBackup = control->controlParam->pEQNB_BandDefinition;
|
|
void *prodPtrBackup = control->controlParam->pPR_EQNB_BandDefinition;
|
|
void *headroomPtrBackup = control->headroomParams->pHeadroomDefinition;
|
|
|
|
memcpy(headroomPtrBackup, preset->headroomParams->pHeadroomDefinition,
|
|
sizeof(*control->headroomParams->pHeadroomDefinition) * LVM_HEADROOM_MAX_NBANDS);
|
|
memcpy(eqnbPtrBackup, preset->controlParams->pEQNB_BandDefinition,
|
|
sizeof(*control->controlParam->pEQNB_BandDefinition) * LVM_EQNB_MAX_BANDS_NBR);
|
|
memcpy(prodPtrBackup, preset->controlParams->pPR_EQNB_BandDefinition,
|
|
sizeof(*control->controlParam->pPR_EQNB_BandDefinition) * LVM_EQNB_MAX_BANDS_NBR);
|
|
|
|
memcpy(control->headroomParams, preset->headroomParams, sizeof(*control->headroomParams));
|
|
#endif
|
|
|
|
memcpy(control->controlParam, preset->controlParams, sizeof(*control->controlParam));
|
|
memcpy(control->instParams, preset->instParams, sizeof(*control->instParams));
|
|
|
|
#ifdef ALGORITHM_EQNB
|
|
control->headroomParams->pHeadroomDefinition = headroomPtrBackup;
|
|
control->controlParam->pEQNB_BandDefinition = eqnbPtrBackup;
|
|
control->controlParam->pPR_EQNB_BandDefinition = prodPtrBackup;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
PRINTF("[EAP_STREAMER] selected preset ID (%c, resolved as index %d) is out of defined presets.\r\n",
|
|
get_app_data()->lastPreset, presetIndex);
|
|
}
|
|
}
|
|
|
|
#ifdef ALGORITHM_PSA
|
|
// EAP_PSA_Bands = (LVM_INT16)ControlParamSet_internal.PSA_NumBands;
|
|
#endif
|
|
|
|
LVM_Status = EAP_SetFSandChannels(args);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
|
|
control->instParams->MaxBlockSize = MAX_SAMPLE_SIZE;
|
|
|
|
/******************************************************************************
|
|
Allocate memory
|
|
Force alignment by allocating extra memory
|
|
*******************************************************************************/
|
|
LVM_Status = LVM_GetMemoryTable(LVM_NULL, &EAP_MemTab, control->instParams);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
|
|
/* Initialize order variable */
|
|
for (i = 0; i < LVM_NR_MEMORY_REGIONS; i++)
|
|
{
|
|
order[i] = i;
|
|
}
|
|
|
|
/* Sort region indexes by region size */
|
|
for (i = 0; i < (LVM_NR_MEMORY_REGIONS - 1); i++)
|
|
{
|
|
minIdx = i;
|
|
for (j = i + 1; j < LVM_NR_MEMORY_REGIONS; j++)
|
|
if (EAP_MemTab.Region[order[j]].Size < EAP_MemTab.Region[order[minIdx]].Size)
|
|
minIdx = j;
|
|
|
|
/* Swap indexes */
|
|
temp32 = order[minIdx];
|
|
order[minIdx] = order[i];
|
|
order[i] = temp32;
|
|
}
|
|
|
|
/* Allocate regions in order from largest to smallest */
|
|
for (j = (LVM_NR_MEMORY_REGIONS - 1); j >= 0; j--)
|
|
{
|
|
/* Log the memory size */
|
|
if (EAP_MemTab.Region[order[j]].Size != 0)
|
|
{
|
|
temp32 = (LVM_INT32)osa_malloc(EAP_MemTab.Region[order[j]].Size + (LVM_UINT32)MallocAlign);
|
|
if (!temp32)
|
|
{
|
|
return LVM_NULLADDRESS;
|
|
}
|
|
EAP_MemTab.Region[order[j]].pBaseAddress = (LVM_INT8 *)(temp32 + MallocAlign);
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
Initialize
|
|
*******************************************************************************/
|
|
/*
|
|
* Get an EAP Instance
|
|
*/
|
|
control->instParams->Platform = PLATFORM_ID;
|
|
EAP_hInstance = LVM_NULL; /* Initialise to NULL */
|
|
LVM_Status = LVM_GetInstanceHandle(&EAP_hInstance, /* Init sets the instance handle */
|
|
&EAP_MemTab, control->instParams);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
|
|
#ifdef ALGORITHM_EQNB
|
|
{
|
|
// set headroom param config
|
|
LVM_Status = LVM_SetHeadroomParams(EAP_hInstance, control->headroomParams);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
Call set control parameters
|
|
- propagate the configuration to EAP
|
|
*******************************************************************************/
|
|
LVM_Status = LVM_SetControlParameters(EAP_hInstance, control->controlParam);
|
|
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
else
|
|
{
|
|
/* ready for first EAP execute */
|
|
first_exec = true;
|
|
#if (ALGORITHM_XO == 1)
|
|
get_app_data()->lastXOOperatingMode = control->controlParam->XO_OperatingMode;
|
|
#endif
|
|
eap_att_register_handle(EAP_hInstance);
|
|
}
|
|
return LVM_Status;
|
|
}
|
|
|
|
int EAP_Execute(void *arg, void *inputBuffer, int size)
|
|
{
|
|
/* Function call status */
|
|
LVM_ReturnStatus_en LVM_Status;
|
|
LVM_INT16 *outBuffer[2] = {(LVM_INT16 *)inputBuffer, NULL};
|
|
|
|
int num_channel = *(int *)arg;
|
|
if (num_channel < 1)
|
|
{
|
|
return LVM_OUTOFRANGE;
|
|
}
|
|
#if (ALGORITHM_XO == 1)
|
|
eap_att_control_t *control = get_eap_att_control();
|
|
app_data_t *app_data = get_app_data();
|
|
if (first_exec)
|
|
{
|
|
first_exec = false;
|
|
app_data->eap_args.xo_enabled = false;
|
|
|
|
if ((control->controlParam->XO_OperatingMode == LVM_MODE_ON))
|
|
{
|
|
// indicate that xo is enabled to enable proper chunks delivery for MONO source format by maestro
|
|
// streamer
|
|
app_data->eap_args.xo_enabled = true;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
eap_xo_out_buffer[i] = osa_malloc(size * num_channel);
|
|
if (eap_xo_out_buffer[i] != NULL)
|
|
{
|
|
outBuffer[i] = eap_xo_out_buffer[i];
|
|
}
|
|
else
|
|
{
|
|
return LVM_NULLADDRESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (app_data->lastXOOperatingMode == LVM_MODE_ON)
|
|
{
|
|
outBuffer[0] = eap_xo_out_buffer[0];
|
|
outBuffer[1] = eap_xo_out_buffer[1];
|
|
}
|
|
#endif
|
|
/* size of each sample is 2 bytes */
|
|
size = size >> 1;
|
|
|
|
EAP_AudioTime += LVM_FRAME_SIZE_MS;
|
|
|
|
LVM_Status = LVM_Process(EAP_hInstance, /* Instance handle */
|
|
(LVM_INT16 *)inputBuffer, /* Input buffer */
|
|
outBuffer, /* Output buffer */
|
|
size / num_channel, /* Number of samples to process */
|
|
EAP_AudioTime); /* Audio Time*/
|
|
|
|
#if (ALGORITHM_XO == 1)
|
|
if (app_data->lastXOOperatingMode)
|
|
{
|
|
/* Interleave data - mix low and high band output of crossover (in case of stereo input take just right
|
|
* channel)*/
|
|
for (int i = 0; i < size / num_channel; i++)
|
|
{
|
|
*((LVM_INT16 *)inputBuffer + 2 * i) = *(outBuffer[0] + num_channel * i);
|
|
*((LVM_INT16 *)inputBuffer + 2 * i + 1) = *(outBuffer[1] + num_channel * i);
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef ALGORITHM_AVL
|
|
LVM_GetAVLGain(EAP_hInstance, &avlGain);
|
|
#endif
|
|
|
|
#ifdef ALGORITHM_PSA
|
|
if (EAP_AudioTime > (EAP_PSA_StartOffset + EAP_PSA_AudioTime1))
|
|
{
|
|
if (!EAP_PSA_Data_Lock)
|
|
{
|
|
// save calculated PSA data into global buffer
|
|
LVM_GetSpectrum(EAP_hInstance, EAP_PSA_CurrPeaks, EAP_PSA_PastPeaks, EAP_PSA_BandFreq, EAP_PSA_AudioTime1);
|
|
}
|
|
EAP_PSA_AudioTime1 += (LVM_UINT32)EAP_PSA_DisplayTimeInc;
|
|
}
|
|
#endif
|
|
|
|
return LVM_Status;
|
|
}
|
|
|
|
LVM_ReturnStatus_en EAP_SetFSandChannels(ext_proc_args *args)
|
|
{
|
|
LVM_ReturnStatus_en LVM_Status = LVM_SUCCESS;
|
|
eap_att_control_t *control = get_eap_att_control();
|
|
switch (args->sample_rate)
|
|
{
|
|
case 4000:
|
|
LVM_Status = LVM_OUTOFRANGE;
|
|
break;
|
|
case 8000:
|
|
control->controlParam->SampleRate = LVM_FS_8000;
|
|
break;
|
|
case 11025:
|
|
control->controlParam->SampleRate = LVM_FS_11025;
|
|
break;
|
|
case 12000:
|
|
control->controlParam->SampleRate = LVM_FS_12000;
|
|
break;
|
|
case 16000:
|
|
control->controlParam->SampleRate = LVM_FS_16000;
|
|
break;
|
|
case 22050:
|
|
control->controlParam->SampleRate = LVM_FS_22050;
|
|
break;
|
|
case 24000:
|
|
control->controlParam->SampleRate = LVM_FS_24000;
|
|
break;
|
|
case 32000:
|
|
control->controlParam->SampleRate = LVM_FS_32000;
|
|
break;
|
|
case 44100:
|
|
control->controlParam->SampleRate = LVM_FS_44100;
|
|
break;
|
|
case 48000:
|
|
control->controlParam->SampleRate = LVM_FS_48000;
|
|
break;
|
|
case 64000:
|
|
case 88200:
|
|
case 96000:
|
|
case 128000:
|
|
case 176400:
|
|
case 192000:
|
|
LVM_Status = LVM_OUTOFRANGE;
|
|
break;
|
|
}
|
|
switch (args->num_channels)
|
|
{
|
|
case 1:
|
|
control->controlParam->SourceFormat = LVM_MONO;
|
|
break;
|
|
case 2:
|
|
control->controlParam->SourceFormat = LVM_STEREO;
|
|
break;
|
|
}
|
|
if (LVM_Status == LVM_OUTOFRANGE)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
else
|
|
{
|
|
return LVM_SUCCESS;
|
|
}
|
|
}
|
|
|
|
int EAP_Deinit(void)
|
|
{
|
|
LVM_ReturnStatus_en LVM_Status; /* Function call status */
|
|
LVM_UINT16 i; /* loop index */
|
|
LVM_INT32 temp32; /* temporary address */
|
|
|
|
/*
|
|
* Free memory
|
|
*/
|
|
LVM_Status = LVM_GetMemoryTable(EAP_hInstance, &EAP_MemTab, LVM_NULL);
|
|
if (LVM_Status != LVM_SUCCESS)
|
|
{
|
|
return LVM_Status;
|
|
}
|
|
|
|
for (i = 0; i < LVM_NR_MEMORY_REGIONS; i++)
|
|
{
|
|
if (EAP_MemTab.Region[i].Size != 0)
|
|
{
|
|
temp32 = (LVM_INT32)EAP_MemTab.Region[i].pBaseAddress - MallocAlign;
|
|
osa_free((LVM_INT8 *)temp32);
|
|
}
|
|
}
|
|
#if (ALGORITHM_XO == 1)
|
|
if (get_app_data()->lastXOOperatingMode)
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
osa_free(eap_xo_out_buffer[i]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
EAP_hInstance = LVM_NULL;
|
|
return LVM_Status;
|
|
}
|
|
|
|
eap_att_code_t register_post_process(void *streamer)
|
|
{
|
|
ELEMENT_PROPERTY_T prop;
|
|
get_app_data()->lastPreset = get_eap_att_control()->eapPreset;
|
|
|
|
PRINTF("[EAP_STREAMER] registering post process EAP\r\n");
|
|
|
|
EXT_PROCESS_DESC_T eap_proc = {EAP_Init, EAP_Execute, EAP_Deinit, &get_app_data()->eap_args, 0};
|
|
|
|
prop.prop = PROP_EAP_FPOINT;
|
|
prop.val = (uintptr_t)&eap_proc;
|
|
|
|
if (streamer_set_property(streamer, prop, true) == 0)
|
|
{
|
|
return kEapAttCodeOk;
|
|
}
|
|
else
|
|
{
|
|
PRINTF("[EAP_STREAMER] EAP post processor registration failed\r\n");
|
|
}
|
|
return kEapAttCodeError;
|
|
}
|
|
|
|
#endif /* EAP_PROC */
|