eas_chorus.c revision 56c99cd2c2c1e6ab038dac5fced5b92ccf11ff6c
1a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 2a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 3a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * File: 4a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * eas_chorus.c 5a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 6a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Contents and purpose: 7a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Contains the implementation of the Chorus effect. 8a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 10a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Copyright Sonic Network Inc. 2006 11a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 12a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Licensed under the Apache License, Version 2.0 (the "License"); 13a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * you may not use this file except in compliance with the License. 14a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * You may obtain a copy of the License at 15a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 16a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * http://www.apache.org/licenses/LICENSE-2.0 17a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 18a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Unless required by applicable law or agreed to in writing, software 19a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * distributed under the License is distributed on an "AS IS" BASIS, 20a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * See the License for the specific language governing permissions and 22a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * limitations under the License. 23a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 24a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 25a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Revision Control: 26a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * $Revision: 499 $ 27a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ 28a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 29a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 30a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 31a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_data.h" 32a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_effects.h" 33a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_math.h" 34a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_chorusdata.h" 35a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_chorus.h" 36a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_config.h" 37a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_host.h" 38a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf#include "eas_report.h" 39a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 40a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/* prototypes for effects interface */ 41a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); 42a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); 43a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); 44a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); 45a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); 46a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 47a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/* common effects interface for configuration module */ 48a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafconst S_EFFECTS_INTERFACE EAS_Chorus = 49a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 50a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusInit, 51a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusProcess, 52a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusShutdown, 53a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusGetParam, 54a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusSetParam 55a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 56a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 57a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 58a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 59a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf//LFO shape table used by the chorus, larger table would sound better 60a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf//this is a sine wave, where 32767 = 1.0 61a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { 62a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, 63a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, 64a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, 65a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, 66a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, 67a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, 68a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, 69a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, 70a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 71a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf}; 72a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 73a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 74a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * InitializeChorus() 75a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 768a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Purpose: Initializes chorus parameters 77a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 78a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 79a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Inputs: 80a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 81a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 82a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 83a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 84a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 85a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) 86a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 87a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf S_CHORUS_OBJECT *pChorusData; 88a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf S_CHORUS_PRESET *pPreset; 89a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 index; 90a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 91a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* check Configuration Module for data allocation */ 92a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (pEASData->staticMemoryModel) 93a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); 94a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 95a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* allocate dynamic memory */ 96a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf else 97a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); 98a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 99a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (pChorusData == NULL) 100a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 101a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } 102a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return EAS_ERROR_MALLOC_FAILED; 103a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 104a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 105a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* clear the structure */ 106a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); 107a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 108a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusReadInPresets(pChorusData); 109a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 110a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* set some default values */ 111a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; 112a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; 113a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; 114a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; 115a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; 116a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 117a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //chorus rate and depth need some massaging from preset value (which is sample rate independent) 118a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 119a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //convert rate from steps of .05 Hz to value which can be used as phase increment, 120a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits 121a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; 1228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf //computing it as below allows rate steps to be evenly spaced 123a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //uses 32 bit divide, but only once when new value is selected 124a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nRate = (EAS_I16) 125a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 1268a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 127a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction 128a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //want to compute ((depth * sampleRate)/20000) 129a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //use the following approximation since 105/32 is roughly 65536/20000 130a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /*lint -e{704} use shift for performance */ 131a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nDepth = (EAS_I16) 132a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 133a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 134a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nLevel = pChorusData->m_nLevel; 135a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 136a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //zero delay memory for chorus 137a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (index = CHORUS_L_SIZE - 1; index >= 0; index--) 138a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 139a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusDelayL[index] = 0; 140a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 141a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (index = CHORUS_R_SIZE - 1; index >= 0; index--) 1428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf { 143a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusDelayR[index] = 0; 144a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 145a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 146a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //init delay line index, these are used to implement circular delay buffer 147a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusIndexL = 0; 148a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusIndexR = 0; 149a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 1508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf //init LFO phase 151a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //16 bit whole part, 16 bit fraction 152a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->lfoLPhase = 0; 153a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; 154a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 155a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //init chorus delay position 156a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //right now chorus delay is a compile-time value, as is sample rate 157a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); 158a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 159a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //now copy from the new preset into Chorus 160a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; 161a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 162a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nLevel = pPreset->m_nLevel; 163a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nRate = pPreset->m_nRate; 164a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nDepth = pPreset->m_nDepth; 165a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 166a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nRate = (EAS_I16) 167a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 168a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 169a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /*lint -e{704} use shift for performance */ 170a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->m_nDepth = (EAS_I16) 171a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 172a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 173a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pInstData = pChorusData; 174a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 175a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return EAS_SUCCESS; 176a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} /* end ChorusInit */ 177a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 178a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 179a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * WeightedTap() 180a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 181a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Purpose: Does fractional array look-up using linear interpolation 182d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf * 183a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * first convert indexDesired to actual desired index by taking into account indexReference 184a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * then do linear interpolation between two actual samples using fractional part 185a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 186d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf * Inputs: 187a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * array: pointer to array of signed 16 bit values, typically either PCM data or control data 188a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * indexReference: the circular buffer relative offset 189d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) 190a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * indexLimit: the total size of the array, used to compute buffer wrap 191a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 192a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 193a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Value from the input array, linearly interpolated between two actual data values 194a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 195a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 196d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf*/ 197a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) 198a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 199d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf EAS_I16 index; 200a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I16 fraction; 201a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I16 val1; 202a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I16 val2; 203d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf 204d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf //separate indexDesired into whole and fractional parts 205d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf /*lint -e{704} use shift for performance */ 206a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf index = (EAS_I16)(indexDesired >> 16); 207a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /*lint -e{704} use shift for performance */ 208d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part 209a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 210a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //adjust whole part by indexReference 211a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf index = indexReference - index; 212a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //make sure we stay within array bounds, this implements circular buffer 213a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf while (index < 0) 214a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 215d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf index += indexLimit; 216a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 217a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 218a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //get two adjacent values from the array 219d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf val1 = array[index]; 220a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 221a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //handle special case when index == 0, else typical case 222d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf if (index == 0) 223d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf { 224d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf val2 = array[indexLimit-1]; //get last value from array 225a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 226a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf else 227a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 228d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf val2 = array[index-1]; //get previous value from array 229a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 230a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 231a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //compute linear interpolation as (val1 + ((val2-val1)*fraction)) 232a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); 233a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} 234d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf 235a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 236a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * ChorusProcess() 237a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 238a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Purpose: compute the chorus on the input buffer, and mix into output buffer 239a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 240a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 241a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Inputs: 242a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * src: pointer to input buffer of PCM values to be processed 243a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * dst: pointer to output buffer of PCM values we are to sume the result with 244a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * bufSize: the number of sample frames (i.e. stereo samples) in the buffer 245a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 246a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 247a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * None 248a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 249a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 250a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 2518a3efffa5b3fde252675239914118664d36a2c24Thomas Graf//compute the chorus, and mix into output buffer 252a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) 253a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 254a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 ix; 255a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 nChannelNumber; 256a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I16 lfoValueLeft; 257a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I16 lfoValueRight; 258a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 positionOffsetL; 259a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 positionOffsetR; 260a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_PCM tapL; 261a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_PCM tapR; 262a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 tempValue; 263a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_PCM nInputSample; 264a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_I32 nOutputSample; 2658a3efffa5b3fde252675239914118664d36a2c24Thomas Graf EAS_PCM *pIn; 266a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_PCM *pOut; 267a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 268a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf S_CHORUS_OBJECT *pChorusData; 269a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 270a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData = (S_CHORUS_OBJECT*) pInstData; 271a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 272a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //if the chorus is disabled or turned all the way down 273a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) 274a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 275a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (pSrc != pDst) 276a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); 277a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return; 278a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 279a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 280a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) 281a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 282a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf ChorusUpdate(pChorusData); 283a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 284a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 285a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) 286a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 287a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 288a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pIn = pSrc + nChannelNumber; 289a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pOut = pDst + nChannelNumber; 290a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 291a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if(nChannelNumber==0) 292a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 293a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (ix = 0; ix < numSamples; ix++) 294a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 295a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nInputSample = *pIn; 296a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pIn += NUM_OUTPUT_CHANNELS; 297a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 298a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //feed input into chorus delay line 299a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; 300a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 301a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //compute chorus lfo value using phase as fractional index into chorus shape table 302a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number 303a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); 304a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 305a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //scale chorus depth by lfo value to get relative fractional sample index 306a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //index is expressed as 32 bit number with 16 bit fractional part 307a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /*lint -e{703} use shift for performance */ 308a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); 309a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 310a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //add fixed chorus delay to get actual fractional sample index 311a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; 312a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 313a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //get tap value from chorus delay using fractional sample index 314a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); 315a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 316a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //scale by chorus level, then sum with input buffer contents and saturate 317a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); 318a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nOutputSample = SATURATE(tempValue + nInputSample); 319a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 320a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pOut = (EAS_I16)SATURATE(nOutputSample); 321a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pOut += NUM_OUTPUT_CHANNELS; 322a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 323a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 324a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //increment chorus delay index and make it wrap as needed 325a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //this implements circular buffer 326a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) 327a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusIndexL = 0; 328d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf 329d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf //increment fractional lfo phase, and make it wrap as needed 330d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf pChorusData->lfoLPhase += pChorusData->m_nRate; 331d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) 332a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 333ddbe8f6c417ddba11f32e1f36bbfbdee8a598a36Thomas Graf pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); 334a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 335a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 336a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 337a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf else 338a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 339a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf for (ix = 0; ix < numSamples; ix++) 340a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 341a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nInputSample = *pIn; 3428a3efffa5b3fde252675239914118664d36a2c24Thomas Graf pIn += NUM_OUTPUT_CHANNELS; 343a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 344a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //feed input into chorus delay line 345a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; 346a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 347a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //compute chorus lfo value using phase as fractional index into chorus shape table 348a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number 349a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); 350a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 351a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //scale chorus depth by lfo value to get relative fractional sample index 352a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //index is expressed as 32 bit number with 16 bit fractional part 353a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /*lint -e{703} use shift for performance */ 354a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); 3558a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 356a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //add fixed chorus delay to get actual fractional sample index 357a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; 358a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 359a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //get tap value from chorus delay using fractional sample index 360a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); 361a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 362a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //scale by chorus level, then sum with output buffer contents and saturate 363a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); 364a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf nOutputSample = SATURATE(tempValue + nInputSample); 365a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 366a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pOut = (EAS_I16)SATURATE(nOutputSample); 367a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pOut += NUM_OUTPUT_CHANNELS; 3688a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 369a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //increment chorus delay index and make it wrap as needed 370a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //this implements circular buffer 371a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) 372a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->chorusIndexR = 0; 373a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 374a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf //increment fractional lfo phase, and make it wrap as needed 375a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->lfoRPhase += pChorusData->m_nRate; 376a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) 377a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 378a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); 379a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 380a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 381a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 3828a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 383a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 384a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} /* end ChorusProcess */ 385a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 386a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 387a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 388a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 389a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * ChorusShutdown() 390a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 391a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Purpose: 392a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Initializes the Chorus effect. 393a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 394a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Inputs: 395a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * pInstData - handle to instance data 3968a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 397a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 398a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 399a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 400a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Side Effects: 401a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 402a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 403a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 404a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) 405a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 406a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf /* check Configuration Module for static memory allocation */ 4078a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!pEASData->staticMemoryModel) 408a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf EAS_HWFree(pEASData->hwInstData, pInstData); 409a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return EAS_SUCCESS; 4108a3efffa5b3fde252675239914118664d36a2c24Thomas Graf} /* end ChorusShutdown */ 411a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 412a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 413a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * ChorusGetParam() 414a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 415a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Purpose: 416a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Get a Chorus parameter 417a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 418a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Inputs: 419a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * pInstData - handle to instance data 420a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * param - parameter index 421a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * *pValue - pointer to variable to hold retrieved value 4228a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 423a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 424a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 425a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 426a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Side Effects: 427a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 428a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 429a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 430a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) 431a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 432a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf S_CHORUS_OBJECT *p; 433a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 434a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf p = (S_CHORUS_OBJECT*) pInstData; 435a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 4368a3efffa5b3fde252675239914118664d36a2c24Thomas Graf switch (param) 437a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 438a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_BYPASS: 4398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *pValue = (EAS_I32) p->bypass; 440a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 441a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_PRESET: 442a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pValue = (EAS_I8) p->m_nCurrentChorus; 443a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 444a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_RATE: 445a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pValue = (EAS_I32) p->m_nRate; 446a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 4478a3efffa5b3fde252675239914118664d36a2c24Thomas Graf case EAS_PARAM_CHORUS_DEPTH: 448a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pValue = (EAS_I32) p->m_nDepth; 449a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 450a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_LEVEL: 451a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *pValue = (EAS_I32) p->m_nLevel; 452a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 453a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf default: 454a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return EAS_ERROR_INVALID_PARAMETER; 455a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf } 456a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf return EAS_SUCCESS; 457a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf} /* end ChorusGetParam */ 458a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 459a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 460a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf/*---------------------------------------------------------------------------- 461a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * ChorusSetParam() 462a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 463a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Purpose: 464a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Set a Chorus parameter 465a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 4668a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Inputs: 467a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * pInstData - handle to instance data 468a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * param - parameter index 4698a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * *pValue - new paramter value 470a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 471a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Outputs: 472a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 473a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 474a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * Side Effects: 475a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf * 476a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf *---------------------------------------------------------------------------- 477a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf*/ 478a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Grafstatic EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) 479a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf{ 480a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf S_CHORUS_OBJECT *p; 481a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 482a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf p = (S_CHORUS_OBJECT*) pInstData; 483a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf 484a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf switch (param) 485a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf { 486a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_BYPASS: 487a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf p->bypass = (EAS_BOOL) value; 488a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf break; 489a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf case EAS_PARAM_CHORUS_PRESET: 490a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && 491a7469ce758fac3631df6ce72eb3f89150070e7f8Thomas Graf value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) 492 return EAS_ERROR_INVALID_PARAMETER; 493 p->m_nNextChorus = (EAS_I8)value; 494 break; 495 case EAS_PARAM_CHORUS_RATE: 496 if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX) 497 return EAS_ERROR_INVALID_PARAMETER; 498 p->m_nRate = (EAS_I16) value; 499 break; 500 case EAS_PARAM_CHORUS_DEPTH: 501 if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX) 502 return EAS_ERROR_INVALID_PARAMETER; 503 p->m_nDepth = (EAS_I16) value; 504 break; 505 case EAS_PARAM_CHORUS_LEVEL: 506 if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX) 507 return EAS_ERROR_INVALID_PARAMETER; 508 p->m_nLevel = (EAS_I16) value; 509 break; 510 511 default: 512 return EAS_ERROR_INVALID_PARAMETER; 513 } 514 return EAS_SUCCESS; 515} /* end ChorusSetParam */ 516 517 518/*---------------------------------------------------------------------------- 519 * ChorusReadInPresets() 520 *---------------------------------------------------------------------------- 521 * Purpose: sets global Chorus preset bank to defaults 522 * 523 * Inputs: 524 * 525 * Outputs: 526 * 527 *---------------------------------------------------------------------------- 528*/ 529static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) 530{ 531 532 int preset = 0; 533 int defaultPreset = 0; 534 535 //now init any remaining presets to defaults 536 for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) 537 { 538 S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; 539 if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) 540 { 541 pPreset->m_nDepth = 39; 542 pPreset->m_nRate = 30; 543 pPreset->m_nLevel = 32767; 544 } 545 else if (defaultPreset == 1) 546 { 547 pPreset->m_nDepth = 21; 548 pPreset->m_nRate = 45; 549 pPreset->m_nLevel = 25000; 550 } 551 else if (defaultPreset == 2) 552 { 553 pPreset->m_nDepth = 53; 554 pPreset->m_nRate = 25; 555 pPreset->m_nLevel = 32000; 556 } 557 else if (defaultPreset == 3) 558 { 559 pPreset->m_nDepth = 32; 560 pPreset->m_nRate = 37; 561 pPreset->m_nLevel = 29000; 562 } 563 } 564 565 return EAS_SUCCESS; 566} 567 568 569/*---------------------------------------------------------------------------- 570 * ChorusUpdate 571 *---------------------------------------------------------------------------- 572 * Purpose: 573 * Update the Chorus preset parameters as required 574 * 575 * Inputs: 576 * 577 * Outputs: 578 * 579 * 580 * Side Effects: 581 * - chorus paramters will be changed 582 * - m_nCurrentRoom := m_nNextRoom 583 *---------------------------------------------------------------------------- 584*/ 585static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) 586{ 587 S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; 588 589 pChorusData->m_nLevel = pPreset->m_nLevel; 590 pChorusData->m_nRate = pPreset->m_nRate; 591 pChorusData->m_nDepth = pPreset->m_nDepth; 592 593 pChorusData->m_nRate = (EAS_I16) 594 ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 595 596 /*lint -e{704} use shift for performance */ 597 pChorusData->m_nDepth = (EAS_I16) 598 (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 599 600 pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; 601 602 return EAS_SUCCESS; 603 604} /* end ChorusUpdate */ 605