| 1 | /****************************************************************************** |
|---|
| 2 | * (c)2011 Broadcom Corporation |
|---|
| 3 | * |
|---|
| 4 | * This program is the proprietary software of Broadcom Corporation and/or its licensors, |
|---|
| 5 | * and may only be used, duplicated, modified or distributed pursuant to the terms and |
|---|
| 6 | * conditions of a separate, written license agreement executed between you and Broadcom |
|---|
| 7 | * (an "Authorized License"). Except as set forth in an Authorized License, Broadcom grants |
|---|
| 8 | * no license (express or implied), right to use, or waiver of any kind with respect to the |
|---|
| 9 | * Software, and Broadcom expressly reserves all rights in and to the Software and all |
|---|
| 10 | * intellectual property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU |
|---|
| 11 | * HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY |
|---|
| 12 | * NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. |
|---|
| 13 | * |
|---|
| 14 | * Except as expressly set forth in the Authorized License, |
|---|
| 15 | * |
|---|
| 16 | * 1. This program, including its structure, sequence and organization, constitutes the valuable trade |
|---|
| 17 | * secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof, |
|---|
| 18 | * and to use this information only in connection with your use of Broadcom integrated circuit products. |
|---|
| 19 | * |
|---|
| 20 | * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
|---|
| 21 | * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR |
|---|
| 22 | * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO |
|---|
| 23 | * THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES |
|---|
| 24 | * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, |
|---|
| 25 | * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION |
|---|
| 26 | * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF |
|---|
| 27 | * USE OR PERFORMANCE OF THE SOFTWARE. |
|---|
| 28 | * |
|---|
| 29 | * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS |
|---|
| 30 | * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR |
|---|
| 31 | * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR |
|---|
| 32 | * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF |
|---|
| 33 | * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT |
|---|
| 34 | * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE |
|---|
| 35 | * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF |
|---|
| 36 | * ANY LIMITED REMEDY. |
|---|
| 37 | * |
|---|
| 38 | * $brcm_Workfile: nexus_audio_equalizer.c $ |
|---|
| 39 | * $brcm_Revision: 4 $ |
|---|
| 40 | * $brcm_Date: 9/19/11 5:34p $ |
|---|
| 41 | * |
|---|
| 42 | * Module Description: |
|---|
| 43 | * |
|---|
| 44 | * Revision History: |
|---|
| 45 | * |
|---|
| 46 | * $brcm_Log: /nexus/modules/audio/7422/src/nexus_audio_equalizer.c $ |
|---|
| 47 | * |
|---|
| 48 | * 4 9/19/11 5:34p jgarrett |
|---|
| 49 | * SW7231-372: Coverity CID 35386 |
|---|
| 50 | * |
|---|
| 51 | * 3 9/15/11 3:26p jgarrett |
|---|
| 52 | * SWDTV-8673: Adding checks for changing subwoofer/subsonic filters on |
|---|
| 53 | * the fly |
|---|
| 54 | * |
|---|
| 55 | * 2 9/8/11 8:45a jgarrett |
|---|
| 56 | * SWDTV-6627: Adding nexus EQ support |
|---|
| 57 | * |
|---|
| 58 | * 1 8/18/11 5:51p jgarrett |
|---|
| 59 | * SWDTV-6306: Merge DTV APE changes to main branch |
|---|
| 60 | * |
|---|
| 61 | * Nexus_APE_Integration/1 7/1/11 5:50p jgarrett |
|---|
| 62 | * SWDTV-6306: Integrated to latest 7422 baseline and nexus audio |
|---|
| 63 | * directory structure |
|---|
| 64 | * |
|---|
| 65 | * 1 4/11/11 5:52p jgarrett |
|---|
| 66 | * SWDTV-6306: Adding preliminary Nexus APE support for DTV |
|---|
| 67 | * |
|---|
| 68 | *****************************************************************************/ |
|---|
| 69 | #include "nexus_audio_module.h" |
|---|
| 70 | |
|---|
| 71 | BDBG_MODULE(nexus_audio_equalizer); |
|---|
| 72 | |
|---|
| 73 | BDBG_OBJECT_ID(NEXUS_AudioEqualizer); |
|---|
| 74 | |
|---|
| 75 | typedef struct NEXUS_AudioEqualizerOutputNode |
|---|
| 76 | { |
|---|
| 77 | BLST_S_ENTRY(NEXUS_AudioEqualizerOutputNode) node; |
|---|
| 78 | NEXUS_AudioOutput output; /* Output attached to this equalizer */ |
|---|
| 79 | } NEXUS_AudioEqualizerOutputNode; |
|---|
| 80 | |
|---|
| 81 | /* You can have at most one of each type in this interface. All types except cascaded PEQ are 1 stage. Cascated PEQ is up to NEXUS_MAX_CASCADED_PARAMETRIC_EQ stages. Subwoofer/Subsonic are two additional. */ |
|---|
| 82 | #define NEXUS_AUDIO_EQUALIZER_MAX_STAGES ((2+NEXUS_AUDIO_EQUALIZER_MAX_ADDITIONAL_MODE) + NEXUS_MAX_CASCADED_PARAMETRIC_EQ + 2) |
|---|
| 83 | #define EQ_STAGE_ID_INVALID (0xffffffff) |
|---|
| 84 | |
|---|
| 85 | typedef struct NEXUS_AudioEqualizer |
|---|
| 86 | { |
|---|
| 87 | BDBG_OBJECT(NEXUS_AudioEqualizer) |
|---|
| 88 | /* Is this opened? */ |
|---|
| 89 | bool opened; |
|---|
| 90 | /* Current Settings */ |
|---|
| 91 | NEXUS_AudioEqualizerSettings settings; |
|---|
| 92 | /* Stage List. Stages are allocated per nexus equalizer, while APE Equalizers are allocated per-output. */ |
|---|
| 93 | unsigned numStages; |
|---|
| 94 | BAPE_EqualizerStageHandle stages[NEXUS_AUDIO_EQUALIZER_MAX_STAGES]; |
|---|
| 95 | unsigned subwooferStageId; |
|---|
| 96 | unsigned subsonicStageId; |
|---|
| 97 | unsigned stageTypeIds[NEXUS_AudioEqualizerMode_eMax]; |
|---|
| 98 | /* List of outputs connected to this equalizer */ |
|---|
| 99 | BLST_S_HEAD(EqualizerOutputList, NEXUS_AudioEqualizerOutputNode) outputList; |
|---|
| 100 | } NEXUS_AudioEqualizer; |
|---|
| 101 | |
|---|
| 102 | #define NEXUS_MAX_AUDIO_EQUALIZERS (12) /* Max number of SRC's on most chips, will likely not use more than 2 or 3 on any chip */ |
|---|
| 103 | static NEXUS_AudioEqualizer g_equalizers[NEXUS_MAX_AUDIO_EQUALIZERS]; |
|---|
| 104 | |
|---|
| 105 | static bool NEXUS_AudioEqualizer_P_IsRunning(NEXUS_AudioEqualizerHandle handle); |
|---|
| 106 | static NEXUS_Error NEXUS_AudioEqualizer_P_CreateConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output); |
|---|
| 107 | static void NEXUS_AudioEqualizer_P_DestroyConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output); |
|---|
| 108 | static NEXUS_Error NEXUS_AudioEqualizer_P_AllocateStages(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings); |
|---|
| 109 | static void NEXUS_AudioEqualizer_P_FreeStages(NEXUS_AudioEqualizerHandle handle); |
|---|
| 110 | static NEXUS_Error NEXUS_AudioEqualizer_P_ApplySettings(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings); |
|---|
| 111 | static void NEXUS_AudioEqualizer_P_OutputSettingsChanged(NEXUS_AudioEqualizerHandle handle); |
|---|
| 112 | |
|---|
| 113 | static NEXUS_AudioEqualizerWindowStep NEXUS_AudioEqualizer_P_WindowStepToNexus(BAPE_EqualizerWindowStep magnum) |
|---|
| 114 | { |
|---|
| 115 | switch ( magnum ) |
|---|
| 116 | { |
|---|
| 117 | default: |
|---|
| 118 | case BAPE_EqualizerWindowStep_eNone: |
|---|
| 119 | return NEXUS_AudioEqualizerWindowStep_eNone; |
|---|
| 120 | case BAPE_EqualizerWindowStep_e170_6: |
|---|
| 121 | return NEXUS_AudioEqualizerWindowStep_e170_6; |
|---|
| 122 | case BAPE_EqualizerWindowStep_e85_3: |
|---|
| 123 | return NEXUS_AudioEqualizerWindowStep_e85_3; |
|---|
| 124 | case BAPE_EqualizerWindowStep_e42_6: |
|---|
| 125 | return NEXUS_AudioEqualizerWindowStep_e42_6; |
|---|
| 126 | case BAPE_EqualizerWindowStep_e21_3: |
|---|
| 127 | return NEXUS_AudioEqualizerWindowStep_e21_3; |
|---|
| 128 | case BAPE_EqualizerWindowStep_e10_6: |
|---|
| 129 | return NEXUS_AudioEqualizerWindowStep_e10_6; |
|---|
| 130 | case BAPE_EqualizerWindowStep_e5_3: |
|---|
| 131 | return NEXUS_AudioEqualizerWindowStep_e5_3; |
|---|
| 132 | case BAPE_EqualizerWindowStep_e2_6: |
|---|
| 133 | return NEXUS_AudioEqualizerWindowStep_e2_6; |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | void NEXUS_AudioEqualizer_GetDefaultSettings( |
|---|
| 138 | NEXUS_AudioEqualizerSettings *pSettings /* [out] Default Settings */ |
|---|
| 139 | ) |
|---|
| 140 | { |
|---|
| 141 | BAPE_EqualizerStageSettings stageSettings; |
|---|
| 142 | unsigned i, j; |
|---|
| 143 | |
|---|
| 144 | BDBG_ASSERT(NULL != pSettings); |
|---|
| 145 | |
|---|
| 146 | BKNI_Memset(pSettings, 0, sizeof(NEXUS_AudioEqualizerSettings)); |
|---|
| 147 | |
|---|
| 148 | /* Propagate nexus settings to stages in the PI */ |
|---|
| 149 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eToneControl, &stageSettings); |
|---|
| 150 | pSettings->modeSettings.tone.bass = stageSettings.modeSettings.toneControl.bassGain; |
|---|
| 151 | pSettings->modeSettings.tone.treble = stageSettings.modeSettings.toneControl.trebleGain; |
|---|
| 152 | pSettings->modeSettings.tone.bassFrequency = stageSettings.modeSettings.toneControl.bassFreq; |
|---|
| 153 | pSettings->modeSettings.tone.trebleFrequency = stageSettings.modeSettings.toneControl.trebleFreq; |
|---|
| 154 | pSettings->modeSettings.tone.bassBandWidthFrequency = stageSettings.modeSettings.toneControl.bassBandwidthFreq; |
|---|
| 155 | pSettings->modeSettings.tone.trebleBandWidthFrequency = stageSettings.modeSettings.toneControl.trebleBandwidthFreq; |
|---|
| 156 | |
|---|
| 157 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eFiveBand, &stageSettings); |
|---|
| 158 | pSettings->modeSettings.fiveBand.gain100Hz = stageSettings.modeSettings.fiveBand.gain100Hz; |
|---|
| 159 | pSettings->modeSettings.fiveBand.gain300Hz = stageSettings.modeSettings.fiveBand.gain300Hz; |
|---|
| 160 | pSettings->modeSettings.fiveBand.gain1000Hz = stageSettings.modeSettings.fiveBand.gain1000Hz; |
|---|
| 161 | pSettings->modeSettings.fiveBand.gain3000Hz = stageSettings.modeSettings.fiveBand.gain3000Hz; |
|---|
| 162 | pSettings->modeSettings.fiveBand.gain10000Hz = stageSettings.modeSettings.fiveBand.gain10000Hz; |
|---|
| 163 | |
|---|
| 164 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eSevenBand, &stageSettings); |
|---|
| 165 | pSettings->modeSettings.parametric.windowStep = NEXUS_AudioEqualizer_P_WindowStepToNexus(stageSettings.modeSettings.sevenBand.windowStep); |
|---|
| 166 | for ( i = 0; i < 7; i++ ) |
|---|
| 167 | { |
|---|
| 168 | pSettings->modeSettings.parametric.bandSettings[i].peak = stageSettings.modeSettings.sevenBand.bandSettings[i].peak; |
|---|
| 169 | pSettings->modeSettings.parametric.bandSettings[i].gain = stageSettings.modeSettings.sevenBand.bandSettings[i].gain; |
|---|
| 170 | pSettings->modeSettings.parametric.bandSettings[i].q = stageSettings.modeSettings.sevenBand.bandSettings[i].q; |
|---|
| 171 | } |
|---|
| 172 | for ( j = 0; j < NEXUS_MAX_CASCADED_PARAMETRIC_EQ; j++ ) |
|---|
| 173 | { |
|---|
| 174 | pSettings->modeSettings.cascadedParametric[j].windowStep = NEXUS_AudioEqualizer_P_WindowStepToNexus(stageSettings.modeSettings.sevenBand.windowStep); |
|---|
| 175 | for ( i = 0; i < 7; i++ ) |
|---|
| 176 | { |
|---|
| 177 | pSettings->modeSettings.cascadedParametric[j].bandSettings[i].peak = stageSettings.modeSettings.sevenBand.bandSettings[i].peak; |
|---|
| 178 | pSettings->modeSettings.cascadedParametric[j].bandSettings[i].gain = stageSettings.modeSettings.sevenBand.bandSettings[i].gain; |
|---|
| 179 | pSettings->modeSettings.cascadedParametric[j].bandSettings[i].q = stageSettings.modeSettings.sevenBand.bandSettings[i].q; |
|---|
| 180 | } |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eCustom, &stageSettings); |
|---|
| 184 | stageSettings.modeSettings.custom.numFilters = pSettings->modeSettings.custom.numFilters; |
|---|
| 185 | for ( i = 0; i < BAPE_EQUALIZER_MAX_CUSTOM_FILTERS; i++ ) |
|---|
| 186 | { |
|---|
| 187 | pSettings->modeSettings.custom.coefficient0[i] = stageSettings.modeSettings.custom.filterCoefficients[i].b0; |
|---|
| 188 | pSettings->modeSettings.custom.coefficient1[i] = stageSettings.modeSettings.custom.filterCoefficients[i].b1; |
|---|
| 189 | pSettings->modeSettings.custom.coefficient2[i] = stageSettings.modeSettings.custom.filterCoefficients[i].b2; |
|---|
| 190 | pSettings->modeSettings.custom.coefficient3[i] = stageSettings.modeSettings.custom.filterCoefficients[i].a1; |
|---|
| 191 | pSettings->modeSettings.custom.coefficient4[i] = stageSettings.modeSettings.custom.filterCoefficients[i].a2; |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eSubwoofer, &stageSettings); |
|---|
| 195 | pSettings->subwooferFrequency = stageSettings.modeSettings.subwoofer.frequency; |
|---|
| 196 | |
|---|
| 197 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eSubsonic, &stageSettings); |
|---|
| 198 | pSettings->subsonicFrequency = stageSettings.modeSettings.subsonic.frequency; |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | NEXUS_AudioEqualizerHandle NEXUS_AudioEqualizer_Open( |
|---|
| 202 | unsigned index, |
|---|
| 203 | const NEXUS_AudioEqualizerSettings *pSettings /* Pass NULL for defaults */ |
|---|
| 204 | ) |
|---|
| 205 | { |
|---|
| 206 | NEXUS_AudioEqualizerSettings defaults; |
|---|
| 207 | NEXUS_AudioEqualizerHandle handle; |
|---|
| 208 | NEXUS_Error errCode; |
|---|
| 209 | unsigned i; |
|---|
| 210 | |
|---|
| 211 | if ( NULL == pSettings ) |
|---|
| 212 | { |
|---|
| 213 | NEXUS_AudioEqualizer_GetDefaultSettings(&defaults); |
|---|
| 214 | pSettings = &defaults; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | if ( index >= NEXUS_MAX_AUDIO_EQUALIZERS ) |
|---|
| 218 | { |
|---|
| 219 | BDBG_ERR(("Equalizer %u not supported. This chipset supports up to %u equalizers.", index, NEXUS_MAX_AUDIO_EQUALIZERS)); |
|---|
| 220 | (void)BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 221 | return NULL; |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | handle = &g_equalizers[index]; |
|---|
| 225 | if ( handle->opened ) |
|---|
| 226 | { |
|---|
| 227 | BDBG_ERR(("Equalizer %u is already open.", index)); |
|---|
| 228 | (void)BERR_TRACE(BERR_INVALID_PARAMETER); |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | BKNI_Memset(handle, 0, sizeof(NEXUS_AudioEqualizer)); |
|---|
| 232 | BDBG_OBJECT_SET(handle, NEXUS_AudioEqualizer); |
|---|
| 233 | handle->opened = true; |
|---|
| 234 | handle->subwooferStageId = EQ_STAGE_ID_INVALID; |
|---|
| 235 | handle->subsonicStageId = EQ_STAGE_ID_INVALID; |
|---|
| 236 | for ( i = 0; i < (unsigned)NEXUS_AudioEqualizerMode_eMax; i++ ) |
|---|
| 237 | { |
|---|
| 238 | handle->stageTypeIds[i] = EQ_STAGE_ID_INVALID; |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | errCode = NEXUS_AudioEqualizer_SetSettings(handle, pSettings); |
|---|
| 242 | if ( errCode ) |
|---|
| 243 | { |
|---|
| 244 | errCode = BERR_TRACE(errCode); |
|---|
| 245 | NEXUS_AudioEqualizer_Close(handle); |
|---|
| 246 | return NULL; |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | return handle; |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| 252 | void NEXUS_AudioEqualizer_Close( |
|---|
| 253 | NEXUS_AudioEqualizerHandle handle |
|---|
| 254 | ) |
|---|
| 255 | { |
|---|
| 256 | NEXUS_AudioEqualizerOutputNode *pNode; |
|---|
| 257 | |
|---|
| 258 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 259 | |
|---|
| 260 | /* Go through all connected outputs and break the connections */ |
|---|
| 261 | while ( NULL != (pNode = BLST_S_FIRST(&handle->outputList)) ) |
|---|
| 262 | { |
|---|
| 263 | (void)NEXUS_AudioOutput_SetEqualizer(pNode->output, NULL); |
|---|
| 264 | } |
|---|
| 265 | |
|---|
| 266 | NEXUS_AudioEqualizer_P_FreeStages(handle); |
|---|
| 267 | |
|---|
| 268 | BKNI_Memset(handle, 0, sizeof(NEXUS_AudioEqualizer)); |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | void NEXUS_AudioEqualizer_GetSettings( |
|---|
| 272 | NEXUS_AudioEqualizerHandle handle, |
|---|
| 273 | NEXUS_AudioEqualizerSettings *pSettings /* [out] Current Settings */ |
|---|
| 274 | ) |
|---|
| 275 | { |
|---|
| 276 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 277 | BDBG_ASSERT(NULL != pSettings); |
|---|
| 278 | BKNI_Memcpy(pSettings, &handle->settings, sizeof(NEXUS_AudioEqualizerSettings)); |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | NEXUS_Error NEXUS_AudioEqualizer_SetSettings( |
|---|
| 282 | NEXUS_AudioEqualizerHandle handle, |
|---|
| 283 | const NEXUS_AudioEqualizerSettings *pSettings |
|---|
| 284 | ) |
|---|
| 285 | { |
|---|
| 286 | NEXUS_Error errCode; |
|---|
| 287 | bool modeChanged = false; |
|---|
| 288 | |
|---|
| 289 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 290 | BDBG_ASSERT(NULL != pSettings); |
|---|
| 291 | |
|---|
| 292 | /* Determine if a mode has changed */ |
|---|
| 293 | if ( (pSettings->mode != handle->settings.mode) || |
|---|
| 294 | (pSettings->secondaryMode != handle->settings.secondaryMode) || |
|---|
| 295 | BKNI_Memcmp(pSettings->additionalModes, handle->settings.additionalModes, sizeof(pSettings->additionalModes)) || |
|---|
| 296 | (pSettings->subwooferFilterEnabled != handle->settings.subwooferFilterEnabled) || |
|---|
| 297 | (pSettings->subsonicFilterEnabled != handle->settings.subsonicFilterEnabled) ) |
|---|
| 298 | { |
|---|
| 299 | /* Can not change modes while running */ |
|---|
| 300 | if ( NEXUS_AudioEqualizer_P_IsRunning(handle) ) |
|---|
| 301 | { |
|---|
| 302 | BDBG_ERR(("Can not change equalizer modes while any connected outputs are running.")); |
|---|
| 303 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | modeChanged = true; |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | if ( modeChanged ) |
|---|
| 310 | { |
|---|
| 311 | /* Free existing stages */ |
|---|
| 312 | NEXUS_AudioEqualizer_P_FreeStages(handle); |
|---|
| 313 | |
|---|
| 314 | errCode = NEXUS_AudioEqualizer_P_AllocateStages(handle, pSettings); |
|---|
| 315 | if ( errCode ) |
|---|
| 316 | { |
|---|
| 317 | NEXUS_AudioEqualizer_P_FreeStages(handle); |
|---|
| 318 | /* Settings are now invalid. Revert to defaults. */ |
|---|
| 319 | NEXUS_AudioEqualizer_GetDefaultSettings(&handle->settings); |
|---|
| 320 | return BERR_TRACE(errCode); |
|---|
| 321 | } |
|---|
| 322 | } |
|---|
| 323 | |
|---|
| 324 | /* Update settings per stage */ |
|---|
| 325 | errCode = NEXUS_AudioEqualizer_P_ApplySettings(handle, pSettings); |
|---|
| 326 | if ( errCode ) |
|---|
| 327 | { |
|---|
| 328 | return BERR_TRACE(errCode); |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | /* Store new settings */ |
|---|
| 332 | BKNI_Memcpy(&handle->settings, pSettings, sizeof(NEXUS_AudioEqualizerSettings)); |
|---|
| 333 | |
|---|
| 334 | /* Force equalizers to be re-allocated on next start call if required */ |
|---|
| 335 | if ( modeChanged ) |
|---|
| 336 | { |
|---|
| 337 | NEXUS_AudioEqualizer_P_OutputSettingsChanged(handle); |
|---|
| 338 | } |
|---|
| 339 | |
|---|
| 340 | return NEXUS_SUCCESS; |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | NEXUS_Error NEXUS_AudioOutput_SetEqualizer( |
|---|
| 344 | NEXUS_AudioOutput output, |
|---|
| 345 | NEXUS_AudioEqualizerHandle equalizer /* Pass NULL to remove any equalizer connected to this output */ |
|---|
| 346 | ) |
|---|
| 347 | { |
|---|
| 348 | NEXUS_AudioOutputData *pData; |
|---|
| 349 | NEXUS_Error errCode; |
|---|
| 350 | |
|---|
| 351 | BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput); |
|---|
| 352 | if ( NULL != equalizer ) |
|---|
| 353 | { |
|---|
| 354 | /* Passing NULL to remove the equalizer is acceptable */ |
|---|
| 355 | BDBG_OBJECT_ASSERT(equalizer, NEXUS_AudioEqualizer); |
|---|
| 356 | } |
|---|
| 357 | |
|---|
| 358 | pData = output->pMixerData; |
|---|
| 359 | if ( NULL == pData ) |
|---|
| 360 | { |
|---|
| 361 | pData = NEXUS_AudioOutput_P_CreateData(output); |
|---|
| 362 | if ( NULL == pData ) |
|---|
| 363 | { |
|---|
| 364 | return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 365 | } |
|---|
| 366 | } |
|---|
| 367 | |
|---|
| 368 | if ( equalizer != pData->equalizer ) |
|---|
| 369 | { |
|---|
| 370 | if ( NEXUS_AudioOutput_P_IsRunning(output) ) |
|---|
| 371 | { |
|---|
| 372 | BDBG_ERR(("Can not change equalizers while an output is running.")); |
|---|
| 373 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 374 | } |
|---|
| 375 | if ( pData->equalizer ) |
|---|
| 376 | { |
|---|
| 377 | /* If connected to an EQ already, break the connection */ |
|---|
| 378 | NEXUS_AudioEqualizer_P_DestroyConnection(pData->equalizer, output); |
|---|
| 379 | pData->equalizer = NULL; |
|---|
| 380 | } |
|---|
| 381 | if ( equalizer ) |
|---|
| 382 | { |
|---|
| 383 | errCode = NEXUS_AudioEqualizer_P_CreateConnection(equalizer, output); |
|---|
| 384 | if ( errCode ) |
|---|
| 385 | { |
|---|
| 386 | return BERR_TRACE(errCode); |
|---|
| 387 | } |
|---|
| 388 | pData->equalizer = equalizer; |
|---|
| 389 | } |
|---|
| 390 | if ( pData->input ) |
|---|
| 391 | { |
|---|
| 392 | /* Mixer reconfiguration will be required on the next start/stop */ |
|---|
| 393 | (void)NEXUS_AudioInput_P_OutputSettingsChanged(pData->input, output); |
|---|
| 394 | } |
|---|
| 395 | } |
|---|
| 396 | |
|---|
| 397 | return BERR_SUCCESS; |
|---|
| 398 | } |
|---|
| 399 | |
|---|
| 400 | static bool NEXUS_AudioEqualizer_P_IsRunning(NEXUS_AudioEqualizerHandle handle) |
|---|
| 401 | { |
|---|
| 402 | NEXUS_AudioEqualizerOutputNode *pNode; |
|---|
| 403 | |
|---|
| 404 | for ( pNode = BLST_S_FIRST(&handle->outputList); |
|---|
| 405 | NULL != pNode; |
|---|
| 406 | pNode = BLST_S_NEXT(pNode, node) ) |
|---|
| 407 | { |
|---|
| 408 | if ( NEXUS_AudioOutput_P_IsRunning(pNode->output) ) |
|---|
| 409 | { |
|---|
| 410 | return true; |
|---|
| 411 | } |
|---|
| 412 | } |
|---|
| 413 | |
|---|
| 414 | return false; |
|---|
| 415 | } |
|---|
| 416 | |
|---|
| 417 | static void NEXUS_AudioEqualizer_P_OutputSettingsChanged(NEXUS_AudioEqualizerHandle handle) |
|---|
| 418 | { |
|---|
| 419 | NEXUS_AudioEqualizerOutputNode *pNode; |
|---|
| 420 | |
|---|
| 421 | for ( pNode = BLST_S_FIRST(&handle->outputList); |
|---|
| 422 | NULL != pNode; |
|---|
| 423 | pNode = BLST_S_NEXT(pNode, node) ) |
|---|
| 424 | { |
|---|
| 425 | NEXUS_AudioInput input; |
|---|
| 426 | NEXUS_AudioOutput output; |
|---|
| 427 | NEXUS_AudioOutputData *pData; |
|---|
| 428 | |
|---|
| 429 | output = pNode->output; |
|---|
| 430 | pData = output->pMixerData; |
|---|
| 431 | if ( pData ) |
|---|
| 432 | { |
|---|
| 433 | input = pData->input; |
|---|
| 434 | if ( input ) |
|---|
| 435 | { |
|---|
| 436 | (void)NEXUS_AudioInput_P_OutputSettingsChanged(input, output); |
|---|
| 437 | } |
|---|
| 438 | } |
|---|
| 439 | } |
|---|
| 440 | } |
|---|
| 441 | |
|---|
| 442 | static NEXUS_Error NEXUS_AudioEqualizer_P_CreateConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output) |
|---|
| 443 | { |
|---|
| 444 | NEXUS_AudioOutputData *pData; |
|---|
| 445 | NEXUS_AudioEqualizerOutputNode *pNode; |
|---|
| 446 | |
|---|
| 447 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 448 | BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput); |
|---|
| 449 | |
|---|
| 450 | pData = output->pMixerData; |
|---|
| 451 | if ( NULL == pData ) |
|---|
| 452 | { |
|---|
| 453 | pData = NEXUS_AudioOutput_P_CreateData(output); |
|---|
| 454 | if ( NULL == pData ) |
|---|
| 455 | { |
|---|
| 456 | return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 457 | } |
|---|
| 458 | } |
|---|
| 459 | |
|---|
| 460 | /* Make sure no other connection exists */ |
|---|
| 461 | BDBG_ASSERT(pData->equalizer == NULL); |
|---|
| 462 | |
|---|
| 463 | /* Create node for output */ |
|---|
| 464 | pNode = BKNI_Malloc(sizeof(NEXUS_AudioEqualizerOutputNode)); |
|---|
| 465 | if ( NULL == pNode ) |
|---|
| 466 | { |
|---|
| 467 | return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 468 | } |
|---|
| 469 | BKNI_Memset(pNode, 0, sizeof(NEXUS_AudioEqualizerOutputNode)); |
|---|
| 470 | |
|---|
| 471 | pNode->output = output; |
|---|
| 472 | BLST_S_INSERT_HEAD(&handle->outputList, pNode, node); |
|---|
| 473 | pData->equalizer = handle; |
|---|
| 474 | |
|---|
| 475 | return NEXUS_SUCCESS; |
|---|
| 476 | } |
|---|
| 477 | |
|---|
| 478 | static void NEXUS_AudioEqualizer_P_DestroyConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output) |
|---|
| 479 | { |
|---|
| 480 | NEXUS_AudioOutputData *pData; |
|---|
| 481 | NEXUS_AudioEqualizerOutputNode *pPrev=NULL, *pNode; |
|---|
| 482 | |
|---|
| 483 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 484 | BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput); |
|---|
| 485 | |
|---|
| 486 | pData = output->pMixerData; |
|---|
| 487 | if ( pData ) |
|---|
| 488 | { |
|---|
| 489 | NEXUS_AudioInput input = pData->input; |
|---|
| 490 | |
|---|
| 491 | /* Make sure these are actually connected */ |
|---|
| 492 | BDBG_ASSERT(pData->equalizer == handle); |
|---|
| 493 | |
|---|
| 494 | if ( input ) |
|---|
| 495 | { |
|---|
| 496 | NEXUS_Error errCode; |
|---|
| 497 | |
|---|
| 498 | if ( NEXUS_AudioInput_P_IsRunning(input) ) |
|---|
| 499 | { |
|---|
| 500 | BDBG_WRN(("Forcing input %p to stop on equalizer %p shutdown", input, handle)); |
|---|
| 501 | NEXUS_AudioInput_P_ForceStop(input); |
|---|
| 502 | } |
|---|
| 503 | |
|---|
| 504 | /* Make sure the actual equalizer is destroyed by removing and re-adding the output now that we're sure it's stopped */ |
|---|
| 505 | NEXUS_AudioOutput_RemoveAllInputs(output); |
|---|
| 506 | errCode = NEXUS_AudioOutput_AddInput(output, input); |
|---|
| 507 | /* This had best not fail */ |
|---|
| 508 | BDBG_ASSERT(errCode == BERR_SUCCESS); |
|---|
| 509 | } |
|---|
| 510 | } |
|---|
| 511 | for ( pNode = BLST_S_FIRST(&handle->outputList); |
|---|
| 512 | NULL != pNode; |
|---|
| 513 | pNode = BLST_S_NEXT(pNode, node) ) |
|---|
| 514 | { |
|---|
| 515 | if ( pNode->output == output ) |
|---|
| 516 | { |
|---|
| 517 | /* Unlink the output from the equalizer */ |
|---|
| 518 | if ( pPrev ) |
|---|
| 519 | { |
|---|
| 520 | BLST_S_REMOVE_NEXT(&handle->outputList, pPrev, node); |
|---|
| 521 | } |
|---|
| 522 | else |
|---|
| 523 | { |
|---|
| 524 | BLST_S_REMOVE_HEAD(&handle->outputList, node); |
|---|
| 525 | } |
|---|
| 526 | BKNI_Memset(pNode, 0, sizeof(NEXUS_AudioEqualizerOutputNode)); |
|---|
| 527 | BKNI_Free(pNode); |
|---|
| 528 | break; |
|---|
| 529 | } |
|---|
| 530 | pPrev = pNode; |
|---|
| 531 | } |
|---|
| 532 | } |
|---|
| 533 | |
|---|
| 534 | static unsigned NEXUS_AudioEqualizer_P_GetNumStages(NEXUS_AudioEqualizerMode mode) |
|---|
| 535 | { |
|---|
| 536 | switch ( mode ) |
|---|
| 537 | { |
|---|
| 538 | default: |
|---|
| 539 | case NEXUS_AudioEqualizerMode_eDisabled: |
|---|
| 540 | return 0; |
|---|
| 541 | case NEXUS_AudioEqualizerMode_eTone: |
|---|
| 542 | case NEXUS_AudioEqualizerMode_eFiveBand: |
|---|
| 543 | case NEXUS_AudioEqualizerMode_eParametric: |
|---|
| 544 | case NEXUS_AudioEqualizerMode_eCustom: |
|---|
| 545 | return 1; |
|---|
| 546 | case NEXUS_AudioEqualizerMode_eCascadedParametric: |
|---|
| 547 | return NEXUS_MAX_CASCADED_PARAMETRIC_EQ; /* TODO: This may be smaller */ |
|---|
| 548 | } |
|---|
| 549 | } |
|---|
| 550 | |
|---|
| 551 | static NEXUS_Error NEXUS_AudioEqualizer_P_AllocateStages(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings) |
|---|
| 552 | { |
|---|
| 553 | BAPE_EqualizerStageSettings stageSettings; |
|---|
| 554 | unsigned numStages=0, i, stage; |
|---|
| 555 | BERR_Code errCode; |
|---|
| 556 | bool modeUsed[NEXUS_AudioEqualizerMode_eMax]; |
|---|
| 557 | |
|---|
| 558 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 559 | BDBG_ASSERT(NULL != pSettings); |
|---|
| 560 | |
|---|
| 561 | /* Determine number of stages required */ |
|---|
| 562 | if ( pSettings->bassManagementEnabled ) |
|---|
| 563 | { |
|---|
| 564 | BDBG_ERR(("Bass management is not supported")); |
|---|
| 565 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 566 | } |
|---|
| 567 | |
|---|
| 568 | /* Reset array of visited types */ |
|---|
| 569 | BKNI_Memset(modeUsed, 0, sizeof(modeUsed)); |
|---|
| 570 | |
|---|
| 571 | if ( modeUsed[pSettings->mode] == false || pSettings->mode == NEXUS_AudioEqualizerMode_eDisabled ) |
|---|
| 572 | { |
|---|
| 573 | numStages += NEXUS_AudioEqualizer_P_GetNumStages(pSettings->mode); |
|---|
| 574 | modeUsed[pSettings->mode] = true; |
|---|
| 575 | } |
|---|
| 576 | else |
|---|
| 577 | { |
|---|
| 578 | BDBG_ERR(("The same mode can not be used more than once with the same equalizer")); |
|---|
| 579 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 580 | } |
|---|
| 581 | if ( modeUsed[pSettings->secondaryMode] == false || pSettings->secondaryMode == NEXUS_AudioEqualizerMode_eDisabled ) |
|---|
| 582 | { |
|---|
| 583 | numStages += NEXUS_AudioEqualizer_P_GetNumStages(pSettings->secondaryMode); |
|---|
| 584 | modeUsed[pSettings->secondaryMode] = true; |
|---|
| 585 | } |
|---|
| 586 | else |
|---|
| 587 | { |
|---|
| 588 | BDBG_ERR(("The same mode can not be used more than once with the same equalizer")); |
|---|
| 589 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 590 | } |
|---|
| 591 | for ( i = 0; i < NEXUS_AUDIO_EQUALIZER_MAX_ADDITIONAL_MODE; i++ ) |
|---|
| 592 | { |
|---|
| 593 | if ( modeUsed[pSettings->additionalModes[i]] == false || pSettings->additionalModes[i] == NEXUS_AudioEqualizerMode_eDisabled ) |
|---|
| 594 | { |
|---|
| 595 | numStages += NEXUS_AudioEqualizer_P_GetNumStages(pSettings->additionalModes[i]); |
|---|
| 596 | modeUsed[pSettings->additionalModes[i]] = true; |
|---|
| 597 | } |
|---|
| 598 | else |
|---|
| 599 | { |
|---|
| 600 | BDBG_ERR(("The same mode can not be used more than once with the same equalizer")); |
|---|
| 601 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 602 | } |
|---|
| 603 | } |
|---|
| 604 | if ( pSettings->subsonicFilterEnabled ) |
|---|
| 605 | { |
|---|
| 606 | numStages++; |
|---|
| 607 | } |
|---|
| 608 | if ( pSettings->subwooferFilterEnabled ) |
|---|
| 609 | { |
|---|
| 610 | numStages++; |
|---|
| 611 | } |
|---|
| 612 | if ( numStages > NEXUS_AUDIO_EQUALIZER_MAX_STAGES ) |
|---|
| 613 | { |
|---|
| 614 | BDBG_ERR(("Requested equalizer mode would require %u stages but only %u are available.", NEXUS_AUDIO_EQUALIZER_MAX_STAGES)); |
|---|
| 615 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 616 | } |
|---|
| 617 | |
|---|
| 618 | stage = 0; |
|---|
| 619 | /* Go through and actually allocate the stages */ |
|---|
| 620 | for ( i = (unsigned)NEXUS_AudioEqualizerMode_eTone; |
|---|
| 621 | i < (unsigned)NEXUS_AudioEqualizerMode_eMax; |
|---|
| 622 | i++ ) |
|---|
| 623 | { |
|---|
| 624 | unsigned j, num=1; |
|---|
| 625 | BAPE_EqualizerStageType stageType; |
|---|
| 626 | |
|---|
| 627 | /* Add only modes we are actually using */ |
|---|
| 628 | if ( modeUsed[i] ) |
|---|
| 629 | { |
|---|
| 630 | switch ( i ) |
|---|
| 631 | { |
|---|
| 632 | default: |
|---|
| 633 | case NEXUS_AudioEqualizerMode_eTone: |
|---|
| 634 | stageType = BAPE_EqualizerStageType_eToneControl; |
|---|
| 635 | break; |
|---|
| 636 | case NEXUS_AudioEqualizerMode_eFiveBand: |
|---|
| 637 | stageType = BAPE_EqualizerStageType_eFiveBand; |
|---|
| 638 | break; |
|---|
| 639 | case NEXUS_AudioEqualizerMode_eParametric: |
|---|
| 640 | stageType = BAPE_EqualizerStageType_eSevenBand; |
|---|
| 641 | break; |
|---|
| 642 | case NEXUS_AudioEqualizerMode_eCustom: |
|---|
| 643 | stageType = BAPE_EqualizerStageType_eCustom; |
|---|
| 644 | break; |
|---|
| 645 | case NEXUS_AudioEqualizerMode_eCascadedParametric: |
|---|
| 646 | stageType = BAPE_EqualizerStageType_eSevenBand; |
|---|
| 647 | num = NEXUS_MAX_CASCADED_PARAMETRIC_EQ; |
|---|
| 648 | break; |
|---|
| 649 | } |
|---|
| 650 | |
|---|
| 651 | handle->stageTypeIds[i] = stage; |
|---|
| 652 | BAPE_EqualizerStage_GetDefaultSettings(stageType, &stageSettings); |
|---|
| 653 | for ( j = 0; j < num; j++ ) |
|---|
| 654 | { |
|---|
| 655 | errCode = BAPE_EqualizerStage_Create(NEXUS_AUDIO_DEVICE_HANDLE, &stageSettings, &handle->stages[stage]); |
|---|
| 656 | if ( errCode ) |
|---|
| 657 | { |
|---|
| 658 | errCode = BERR_TRACE(errCode); |
|---|
| 659 | goto err_stage_create; |
|---|
| 660 | } |
|---|
| 661 | stage++; |
|---|
| 662 | } |
|---|
| 663 | } |
|---|
| 664 | } |
|---|
| 665 | |
|---|
| 666 | /* Add subwoofer/subsonic stages also */ |
|---|
| 667 | if ( pSettings->subwooferFilterEnabled ) |
|---|
| 668 | { |
|---|
| 669 | handle->subwooferStageId = stage; |
|---|
| 670 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eSubwoofer, &stageSettings); |
|---|
| 671 | errCode = BAPE_EqualizerStage_Create(NEXUS_AUDIO_DEVICE_HANDLE, &stageSettings, &handle->stages[stage]); |
|---|
| 672 | if ( errCode ) |
|---|
| 673 | { |
|---|
| 674 | errCode = BERR_TRACE(errCode); |
|---|
| 675 | goto err_stage_create; |
|---|
| 676 | } |
|---|
| 677 | stage++; |
|---|
| 678 | } |
|---|
| 679 | if ( pSettings->subsonicFilterEnabled ) |
|---|
| 680 | { |
|---|
| 681 | handle->subsonicStageId = stage; |
|---|
| 682 | BAPE_EqualizerStage_GetDefaultSettings(BAPE_EqualizerStageType_eSubsonic, &stageSettings); |
|---|
| 683 | errCode = BAPE_EqualizerStage_Create(NEXUS_AUDIO_DEVICE_HANDLE, &stageSettings, &handle->stages[stage]); |
|---|
| 684 | if ( errCode ) |
|---|
| 685 | { |
|---|
| 686 | errCode = BERR_TRACE(errCode); |
|---|
| 687 | goto err_stage_create; |
|---|
| 688 | } |
|---|
| 689 | stage++; |
|---|
| 690 | } |
|---|
| 691 | handle->numStages = numStages; |
|---|
| 692 | |
|---|
| 693 | return BERR_SUCCESS; |
|---|
| 694 | |
|---|
| 695 | err_stage_create: |
|---|
| 696 | NEXUS_AudioEqualizer_P_FreeStages(handle); |
|---|
| 697 | return errCode; |
|---|
| 698 | } |
|---|
| 699 | |
|---|
| 700 | static void NEXUS_AudioEqualizer_P_FreeStages(NEXUS_AudioEqualizerHandle handle) |
|---|
| 701 | { |
|---|
| 702 | unsigned i; |
|---|
| 703 | NEXUS_Error errCode; |
|---|
| 704 | NEXUS_AudioInput input; |
|---|
| 705 | NEXUS_AudioOutputData *pData; |
|---|
| 706 | NEXUS_AudioEqualizerOutputNode *pNode; |
|---|
| 707 | |
|---|
| 708 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 709 | |
|---|
| 710 | /* We need to make sure that no outputs are actively using these stages first */ |
|---|
| 711 | for ( pNode = BLST_S_FIRST(&handle->outputList); |
|---|
| 712 | NULL != pNode; |
|---|
| 713 | pNode = BLST_S_NEXT(pNode, node) ) |
|---|
| 714 | { |
|---|
| 715 | /* We need to be sure and release all connections between equalizers and the stages */ |
|---|
| 716 | /* Break the connection between the output and input to force release all the PI resources */ |
|---|
| 717 | pData = pNode->output->pMixerData; |
|---|
| 718 | if ( pData ) |
|---|
| 719 | { |
|---|
| 720 | input = pData->input; |
|---|
| 721 | if ( input ) |
|---|
| 722 | { |
|---|
| 723 | (void)NEXUS_AudioOutput_RemoveAllInputs(pNode->output); |
|---|
| 724 | errCode = NEXUS_AudioOutput_AddInput(pNode->output, input); |
|---|
| 725 | BDBG_ASSERT(errCode == NEXUS_SUCCESS); |
|---|
| 726 | } |
|---|
| 727 | } |
|---|
| 728 | } |
|---|
| 729 | |
|---|
| 730 | for ( i = 0; i < NEXUS_AUDIO_EQUALIZER_MAX_STAGES; i++ ) |
|---|
| 731 | { |
|---|
| 732 | if ( handle->stages[i] ) |
|---|
| 733 | { |
|---|
| 734 | BAPE_EqualizerStage_Destroy(handle->stages[i]); |
|---|
| 735 | handle->stages[i] = NULL; |
|---|
| 736 | } |
|---|
| 737 | } |
|---|
| 738 | |
|---|
| 739 | handle->subwooferStageId = EQ_STAGE_ID_INVALID; |
|---|
| 740 | handle->subsonicStageId = EQ_STAGE_ID_INVALID; |
|---|
| 741 | for ( i = 0; i < (unsigned)NEXUS_AudioEqualizerMode_eMax; i++ ) |
|---|
| 742 | { |
|---|
| 743 | handle->stageTypeIds[i] = EQ_STAGE_ID_INVALID; |
|---|
| 744 | } |
|---|
| 745 | } |
|---|
| 746 | |
|---|
| 747 | static BAPE_EqualizerWindowStep NEXUS_AudioEqualizer_P_WindowStepToMagnum(NEXUS_AudioEqualizerWindowStep nexus) |
|---|
| 748 | { |
|---|
| 749 | switch ( nexus ) |
|---|
| 750 | { |
|---|
| 751 | default: |
|---|
| 752 | case NEXUS_AudioEqualizerWindowStep_eNone: |
|---|
| 753 | return BAPE_EqualizerWindowStep_eNone; |
|---|
| 754 | case NEXUS_AudioEqualizerWindowStep_e170_6: |
|---|
| 755 | return BAPE_EqualizerWindowStep_e170_6; |
|---|
| 756 | case NEXUS_AudioEqualizerWindowStep_e85_3: |
|---|
| 757 | return BAPE_EqualizerWindowStep_e85_3; |
|---|
| 758 | case NEXUS_AudioEqualizerWindowStep_e42_6: |
|---|
| 759 | return BAPE_EqualizerWindowStep_e42_6; |
|---|
| 760 | case NEXUS_AudioEqualizerWindowStep_e21_3: |
|---|
| 761 | return BAPE_EqualizerWindowStep_e21_3; |
|---|
| 762 | case NEXUS_AudioEqualizerWindowStep_e10_6: |
|---|
| 763 | return BAPE_EqualizerWindowStep_e10_6; |
|---|
| 764 | case NEXUS_AudioEqualizerWindowStep_e5_3: |
|---|
| 765 | return BAPE_EqualizerWindowStep_e5_3; |
|---|
| 766 | case NEXUS_AudioEqualizerWindowStep_e2_6: |
|---|
| 767 | return BAPE_EqualizerWindowStep_e2_6; |
|---|
| 768 | } |
|---|
| 769 | } |
|---|
| 770 | |
|---|
| 771 | static NEXUS_Error NEXUS_AudioEqualizer_P_ApplySettings(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings) |
|---|
| 772 | { |
|---|
| 773 | BAPE_EqualizerStageHandle stage; |
|---|
| 774 | BAPE_EqualizerStageSettings stageSettings; |
|---|
| 775 | unsigned i,j; |
|---|
| 776 | BERR_Code errCode; |
|---|
| 777 | |
|---|
| 778 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 779 | BDBG_ASSERT(NULL != pSettings); |
|---|
| 780 | |
|---|
| 781 | /* Propagate nexus settings to stages in the PI */ |
|---|
| 782 | if ( handle->stageTypeIds[NEXUS_AudioEqualizerMode_eTone] != EQ_STAGE_ID_INVALID ) |
|---|
| 783 | { |
|---|
| 784 | stage = handle->stages[handle->stageTypeIds[NEXUS_AudioEqualizerMode_eTone]]; |
|---|
| 785 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 786 | stageSettings.modeSettings.toneControl.bassGain = pSettings->modeSettings.tone.bass; |
|---|
| 787 | stageSettings.modeSettings.toneControl.trebleGain = pSettings->modeSettings.tone.treble; |
|---|
| 788 | stageSettings.modeSettings.toneControl.bassFreq = pSettings->modeSettings.tone.bassFrequency; |
|---|
| 789 | stageSettings.modeSettings.toneControl.trebleFreq = pSettings->modeSettings.tone.trebleFrequency; |
|---|
| 790 | stageSettings.modeSettings.toneControl.bassBandwidthFreq = pSettings->modeSettings.tone.bassBandWidthFrequency; |
|---|
| 791 | stageSettings.modeSettings.toneControl.trebleBandwidthFreq = pSettings->modeSettings.tone.trebleBandWidthFrequency; |
|---|
| 792 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 793 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 794 | } |
|---|
| 795 | if ( handle->stageTypeIds[NEXUS_AudioEqualizerMode_eFiveBand] != EQ_STAGE_ID_INVALID ) |
|---|
| 796 | { |
|---|
| 797 | stage = handle->stages[handle->stageTypeIds[NEXUS_AudioEqualizerMode_eFiveBand]]; |
|---|
| 798 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 799 | stageSettings.modeSettings.fiveBand.gain100Hz = pSettings->modeSettings.fiveBand.gain100Hz; |
|---|
| 800 | stageSettings.modeSettings.fiveBand.gain300Hz = pSettings->modeSettings.fiveBand.gain300Hz; |
|---|
| 801 | stageSettings.modeSettings.fiveBand.gain1000Hz = pSettings->modeSettings.fiveBand.gain1000Hz; |
|---|
| 802 | stageSettings.modeSettings.fiveBand.gain3000Hz = pSettings->modeSettings.fiveBand.gain3000Hz; |
|---|
| 803 | stageSettings.modeSettings.fiveBand.gain10000Hz = pSettings->modeSettings.fiveBand.gain10000Hz; |
|---|
| 804 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 805 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 806 | } |
|---|
| 807 | if ( handle->stageTypeIds[NEXUS_AudioEqualizerMode_eParametric] != EQ_STAGE_ID_INVALID ) |
|---|
| 808 | { |
|---|
| 809 | stage = handle->stages[handle->stageTypeIds[NEXUS_AudioEqualizerMode_eParametric]]; |
|---|
| 810 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 811 | stageSettings.modeSettings.sevenBand.windowStep = NEXUS_AudioEqualizer_P_WindowStepToMagnum(pSettings->modeSettings.parametric.windowStep); |
|---|
| 812 | for ( i = 0; i < 7; i++ ) |
|---|
| 813 | { |
|---|
| 814 | stageSettings.modeSettings.sevenBand.bandSettings[i].peak = pSettings->modeSettings.parametric.bandSettings[i].peak; |
|---|
| 815 | stageSettings.modeSettings.sevenBand.bandSettings[i].gain = pSettings->modeSettings.parametric.bandSettings[i].gain; |
|---|
| 816 | stageSettings.modeSettings.sevenBand.bandSettings[i].q = pSettings->modeSettings.parametric.bandSettings[i].q; |
|---|
| 817 | } |
|---|
| 818 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 819 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 820 | } |
|---|
| 821 | if ( handle->stageTypeIds[NEXUS_AudioEqualizerMode_eCascadedParametric] != EQ_STAGE_ID_INVALID ) |
|---|
| 822 | { |
|---|
| 823 | for ( j = 0; j < NEXUS_MAX_CASCADED_PARAMETRIC_EQ; j++ ) |
|---|
| 824 | { |
|---|
| 825 | stage = handle->stages[handle->stageTypeIds[NEXUS_AudioEqualizerMode_eCascadedParametric]+j]; |
|---|
| 826 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 827 | stageSettings.modeSettings.sevenBand.windowStep = NEXUS_AudioEqualizer_P_WindowStepToMagnum(pSettings->modeSettings.cascadedParametric[j].windowStep); |
|---|
| 828 | for ( i = 0; i < 7; i++ ) |
|---|
| 829 | { |
|---|
| 830 | stageSettings.modeSettings.sevenBand.bandSettings[i].peak = pSettings->modeSettings.cascadedParametric[j].bandSettings[i].peak; |
|---|
| 831 | stageSettings.modeSettings.sevenBand.bandSettings[i].gain = pSettings->modeSettings.cascadedParametric[j].bandSettings[i].gain; |
|---|
| 832 | stageSettings.modeSettings.sevenBand.bandSettings[i].q = pSettings->modeSettings.cascadedParametric[j].bandSettings[i].q; |
|---|
| 833 | } |
|---|
| 834 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 835 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 836 | } |
|---|
| 837 | } |
|---|
| 838 | if ( handle->stageTypeIds[NEXUS_AudioEqualizerMode_eCustom] != EQ_STAGE_ID_INVALID ) |
|---|
| 839 | { |
|---|
| 840 | stage = handle->stages[handle->stageTypeIds[NEXUS_AudioEqualizerMode_eCustom]]; |
|---|
| 841 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 842 | stageSettings.modeSettings.custom.numFilters = pSettings->modeSettings.custom.numFilters; |
|---|
| 843 | BDBG_CASSERT(NEXUS_AUDIO_EQUALIZER_MAX_CUSTOM_COEFFICIENTS==BAPE_EQUALIZER_MAX_CUSTOM_FILTERS); |
|---|
| 844 | for ( i = 0; i < BAPE_EQUALIZER_MAX_CUSTOM_FILTERS; i++ ) |
|---|
| 845 | { |
|---|
| 846 | stageSettings.modeSettings.custom.filterCoefficients[i].b0 = pSettings->modeSettings.custom.coefficient0[i]; |
|---|
| 847 | stageSettings.modeSettings.custom.filterCoefficients[i].b1 = pSettings->modeSettings.custom.coefficient1[i]; |
|---|
| 848 | stageSettings.modeSettings.custom.filterCoefficients[i].b2 = pSettings->modeSettings.custom.coefficient2[i]; |
|---|
| 849 | stageSettings.modeSettings.custom.filterCoefficients[i].a1 = pSettings->modeSettings.custom.coefficient3[i]; |
|---|
| 850 | stageSettings.modeSettings.custom.filterCoefficients[i].a2 = pSettings->modeSettings.custom.coefficient4[i]; |
|---|
| 851 | } |
|---|
| 852 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 853 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 854 | } |
|---|
| 855 | if ( handle->subwooferStageId != EQ_STAGE_ID_INVALID ) |
|---|
| 856 | { |
|---|
| 857 | stage = handle->stages[handle->subwooferStageId]; |
|---|
| 858 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 859 | stageSettings.modeSettings.subwoofer.frequency = pSettings->subwooferFrequency; |
|---|
| 860 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 861 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 862 | } |
|---|
| 863 | if ( handle->subsonicStageId != EQ_STAGE_ID_INVALID ) |
|---|
| 864 | { |
|---|
| 865 | stage = handle->stages[handle->subsonicStageId]; |
|---|
| 866 | BAPE_EqualizerStage_GetSettings(stage, &stageSettings); |
|---|
| 867 | stageSettings.modeSettings.subsonic.frequency = pSettings->subsonicFrequency; |
|---|
| 868 | errCode = BAPE_EqualizerStage_SetSettings(stage, &stageSettings); |
|---|
| 869 | if ( errCode ) { return BERR_TRACE(errCode); } |
|---|
| 870 | } |
|---|
| 871 | |
|---|
| 872 | return NEXUS_SUCCESS; |
|---|
| 873 | } |
|---|
| 874 | |
|---|
| 875 | NEXUS_AudioEqualizerHandle NEXUS_AudioOutput_P_GetEqualizer( |
|---|
| 876 | NEXUS_AudioOutput output |
|---|
| 877 | ) |
|---|
| 878 | { |
|---|
| 879 | NEXUS_AudioOutputData *pData; |
|---|
| 880 | |
|---|
| 881 | BDBG_OBJECT_ASSERT(output, NEXUS_AudioOutput); |
|---|
| 882 | |
|---|
| 883 | pData = output->pMixerData; |
|---|
| 884 | if ( pData ) |
|---|
| 885 | { |
|---|
| 886 | return pData->equalizer; |
|---|
| 887 | } |
|---|
| 888 | return NULL; |
|---|
| 889 | } |
|---|
| 890 | |
|---|
| 891 | void NEXUS_AudioEqualizer_P_GetStages( |
|---|
| 892 | NEXUS_AudioEqualizerHandle handle, |
|---|
| 893 | BAPE_EqualizerStageHandle **pStages, |
|---|
| 894 | unsigned *pNumStages |
|---|
| 895 | ) |
|---|
| 896 | { |
|---|
| 897 | BDBG_OBJECT_ASSERT(handle, NEXUS_AudioEqualizer); |
|---|
| 898 | BDBG_ASSERT(NULL != pStages); |
|---|
| 899 | BDBG_ASSERT(NULL != pNumStages); |
|---|
| 900 | |
|---|
| 901 | *pStages = handle->stages; |
|---|
| 902 | *pNumStages = handle->numStages; |
|---|
| 903 | } |
|---|
| 904 | |
|---|