source: svn/newcon3bcm2_21bu/nexus/modules/audio/7552/src/nexus_audio_equalizer.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 35.9 KB
Line 
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
71BDBG_MODULE(nexus_audio_equalizer);
72
73BDBG_OBJECT_ID(NEXUS_AudioEqualizer);
74
75typedef 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
85typedef 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 */
103static NEXUS_AudioEqualizer g_equalizers[NEXUS_MAX_AUDIO_EQUALIZERS];
104
105static bool NEXUS_AudioEqualizer_P_IsRunning(NEXUS_AudioEqualizerHandle handle);
106static NEXUS_Error NEXUS_AudioEqualizer_P_CreateConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output);
107static void NEXUS_AudioEqualizer_P_DestroyConnection(NEXUS_AudioEqualizerHandle handle, NEXUS_AudioOutput output);
108static NEXUS_Error NEXUS_AudioEqualizer_P_AllocateStages(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings);
109static void NEXUS_AudioEqualizer_P_FreeStages(NEXUS_AudioEqualizerHandle handle);       
110static NEXUS_Error NEXUS_AudioEqualizer_P_ApplySettings(NEXUS_AudioEqualizerHandle handle, const NEXUS_AudioEqualizerSettings *pSettings);
111static void NEXUS_AudioEqualizer_P_OutputSettingsChanged(NEXUS_AudioEqualizerHandle handle);
112
113static 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
137void 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
201NEXUS_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
252void 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
271void 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
281NEXUS_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
343NEXUS_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
400static 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
417static 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
442static 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
478static 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
534static 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
551static 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
695err_stage_create:
696    NEXUS_AudioEqualizer_P_FreeStages(handle);
697    return errCode;           
698}
699
700static 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
747static 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
771static 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
875NEXUS_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
891void 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
Note: See TracBrowser for help on using the repository browser.