449 lines
15 KiB
C
449 lines
15 KiB
C
|
/*
|
||
|
* Copyright (C) 2008 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#ifndef ANDROID_EFFECTREVERB_H_
|
||
|
#define ANDROID_EFFECTREVERB_H_
|
||
|
|
||
|
#include <media/EffectEnvironmentalReverbApi.h>
|
||
|
#include <media/EffectPresetReverbApi.h>
|
||
|
|
||
|
|
||
|
/*------------------------------------
|
||
|
* defines
|
||
|
*------------------------------------
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
CIRCULAR() calculates the array index using modulo arithmetic.
|
||
|
The "trick" is that modulo arithmetic is simplified by masking
|
||
|
the effective address where the mask is (2^n)-1. This only works
|
||
|
if the buffer size is a power of two.
|
||
|
*/
|
||
|
#define CIRCULAR(base,offset,size) (uint32_t)( \
|
||
|
( \
|
||
|
((int32_t)(base)) + ((int32_t)(offset)) \
|
||
|
) \
|
||
|
& size \
|
||
|
)
|
||
|
|
||
|
#define NUM_OUTPUT_CHANNELS 2
|
||
|
#define OUTPUT_CHANNELS CHANNEL_STEREO
|
||
|
|
||
|
#define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX 16384
|
||
|
|
||
|
#define REVERB_NUM_PRESETS REVERB_PRESET_PLATE // REVERB_PRESET_NONE is not included
|
||
|
#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel
|
||
|
|
||
|
|
||
|
// xfade parameters
|
||
|
#define REVERB_XFADE_PERIOD_IN_SECONDS (double) (100.0 / 1000.0) // xfade once every this many seconds
|
||
|
|
||
|
|
||
|
/**********/
|
||
|
/* the entire synth uses various flags in a bit field */
|
||
|
|
||
|
/* if flag is set, synth reset has been requested */
|
||
|
#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */
|
||
|
#define MASK_REVERB_RESET_IS_REQUESTED 0x01
|
||
|
#define MASK_REVERB_RESET_IS_NOT_REQUESTED (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED)
|
||
|
|
||
|
/*
|
||
|
by default, we always want to update ALL channel parameters
|
||
|
when we reset the synth (e.g., during GM ON)
|
||
|
*/
|
||
|
#define DEFAULT_REVERB_FLAGS 0x0
|
||
|
|
||
|
/* coefficients for generating sin, cos */
|
||
|
#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */
|
||
|
/*
|
||
|
int32_t nPanG1 = +1.0 for sin
|
||
|
int32_t nPanG1 = -1.0 for cos
|
||
|
*/
|
||
|
#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
|
||
|
|
||
|
/*************************************************************/
|
||
|
// define the input injection points
|
||
|
#define GUARD 5 // safety guard of this many samples
|
||
|
|
||
|
#define MAX_AP_TIME (int) ((20*65536)/1000) // delay time in time units (65536th of sec)
|
||
|
#define MAX_DELAY_TIME (int) ((65*65536)/1000) // delay time in time units
|
||
|
#define MAX_EARLY_TIME (int) ((65*65536)/1000) // delay time in time units
|
||
|
|
||
|
#define AP0_IN 0
|
||
|
|
||
|
|
||
|
#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number
|
||
|
#define DEFAULT_AP0_GAIN 19400
|
||
|
#define DEFAULT_AP1_GAIN -19400
|
||
|
|
||
|
#define REVERB_DEFAULT_WET 32767
|
||
|
#define REVERB_DEFAULT_DRY 0
|
||
|
|
||
|
#define REVERB_WET_MAX 32767
|
||
|
#define REVERB_WET_MIN 0
|
||
|
#define REVERB_DRY_MAX 32767
|
||
|
#define REVERB_DRY_MIN 0
|
||
|
|
||
|
// constants for reverb density
|
||
|
// The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by
|
||
|
// AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE
|
||
|
#define AP0_TIME_BASE (int)((9*65536)/1000)
|
||
|
#define AP0_TIME_RANGE (int)((4*65536)/1000)
|
||
|
#define AP1_TIME_BASE (int)((12*65536)/1000)
|
||
|
#define AP1_TIME_RANGE (int)((8*65536)/1000)
|
||
|
|
||
|
// constants for reverb diffusion
|
||
|
// The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by
|
||
|
// AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE
|
||
|
#define AP0_GAIN_BASE (int)(9830)
|
||
|
#define AP0_GAIN_RANGE (int)(19660-9830)
|
||
|
#define AP1_GAIN_BASE (int)(6553)
|
||
|
#define AP1_GAIN_RANGE (int)(22936-6553)
|
||
|
|
||
|
|
||
|
enum reverb_state_e {
|
||
|
REVERB_STATE_UNINITIALIZED,
|
||
|
REVERB_STATE_INITIALIZED,
|
||
|
REVERB_STATE_ACTIVE,
|
||
|
};
|
||
|
|
||
|
/* parameters for each allpass */
|
||
|
typedef struct
|
||
|
{
|
||
|
uint16_t m_zApOut; // delay offset for ap out
|
||
|
|
||
|
int16_t m_nApGain; // gain for ap
|
||
|
|
||
|
uint16_t m_zApIn; // delay offset for ap in
|
||
|
|
||
|
} allpass_object_t;
|
||
|
|
||
|
|
||
|
/* parameters for early reflections */
|
||
|
typedef struct
|
||
|
{
|
||
|
uint16_t m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out
|
||
|
|
||
|
int16_t m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap
|
||
|
|
||
|
} early_reflection_object_t;
|
||
|
|
||
|
//demo
|
||
|
typedef struct
|
||
|
{
|
||
|
int16_t m_nRvbLpfFbk;
|
||
|
int16_t m_nRvbLpfFwd;
|
||
|
int16_t m_nRoomLpfFbk;
|
||
|
int16_t m_nRoomLpfFwd;
|
||
|
|
||
|
int16_t m_nEarlyGain;
|
||
|
int16_t m_nEarlyDelay;
|
||
|
int16_t m_nLateGain;
|
||
|
int16_t m_nLateDelay;
|
||
|
|
||
|
early_reflection_object_t m_sEarlyL;
|
||
|
early_reflection_object_t m_sEarlyR;
|
||
|
|
||
|
uint16_t m_nMaxExcursion; //28
|
||
|
int16_t m_nXfadeInterval;
|
||
|
|
||
|
int16_t m_nAp0_ApGain; //30
|
||
|
int16_t m_nAp0_ApOut;
|
||
|
int16_t m_nAp1_ApGain;
|
||
|
int16_t m_nAp1_ApOut;
|
||
|
int16_t m_nDiffusion;
|
||
|
|
||
|
int16_t m_rfu4;
|
||
|
int16_t m_rfu5;
|
||
|
int16_t m_rfu6;
|
||
|
int16_t m_rfu7;
|
||
|
int16_t m_rfu8;
|
||
|
int16_t m_rfu9;
|
||
|
int16_t m_rfu10; //43
|
||
|
|
||
|
} reverb_preset_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
reverb_preset_t m_sPreset[REVERB_NUM_PRESETS]; // array of presets(does not include REVERB_PRESET_NONE)
|
||
|
|
||
|
} reverb_preset_bank_t;
|
||
|
|
||
|
|
||
|
/* parameters for each reverb */
|
||
|
typedef struct
|
||
|
{
|
||
|
/* update counter keeps track of when synth params need updating */
|
||
|
/* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
|
||
|
int16_t m_nUpdateCounter;
|
||
|
|
||
|
uint16_t m_nBaseIndex; // base index for circular buffer
|
||
|
|
||
|
// reverb delay line offsets, allpass parameters, etc:
|
||
|
|
||
|
short m_nRevFbkR; // combine feedback reverb right out with dry left in
|
||
|
short m_zOutLpfL; // left reverb output
|
||
|
|
||
|
allpass_object_t m_sAp0; // allpass 0 (left channel)
|
||
|
|
||
|
uint16_t m_zD0In; // delay offset for delay line D0 in
|
||
|
|
||
|
short m_nRevFbkL; // combine feedback reverb left out with dry right in
|
||
|
short m_zOutLpfR; // right reverb output
|
||
|
|
||
|
allpass_object_t m_sAp1; // allpass 1 (right channel)
|
||
|
|
||
|
uint16_t m_zD1In; // delay offset for delay line D1 in
|
||
|
|
||
|
// delay output taps, notice criss cross order
|
||
|
uint16_t m_zD0Self; // self feeds forward d0 --> d0
|
||
|
|
||
|
uint16_t m_zD1Cross; // cross feeds across d1 --> d0
|
||
|
|
||
|
uint16_t m_zD1Self; // self feeds forward d1 --> d1
|
||
|
|
||
|
uint16_t m_zD0Cross; // cross feeds across d0 --> d1
|
||
|
|
||
|
int16_t m_nSin; // gain for self taps
|
||
|
|
||
|
int16_t m_nCos; // gain for cross taps
|
||
|
|
||
|
int16_t m_nSinIncrement; // increment for gain
|
||
|
|
||
|
int16_t m_nCosIncrement; // increment for gain
|
||
|
|
||
|
int16_t m_nRvbLpfFwd; // reverb feedback lpf forward gain (includes scaling for mixer)
|
||
|
|
||
|
int16_t m_nRvbLpfFbk; // reverb feedback lpf feedback gain
|
||
|
|
||
|
int16_t m_nRoomLpfFwd; // room lpf forward gain (includes scaling for mixer)
|
||
|
|
||
|
int16_t m_nRoomLpfFbk; // room lpf feedback gain
|
||
|
|
||
|
uint16_t m_nXfadeInterval; // update/xfade after this many samples
|
||
|
|
||
|
uint16_t m_nXfadeCounter; // keep track of when to xfade
|
||
|
|
||
|
int16_t m_nPhase; // -1 <= m_nPhase < 1
|
||
|
// but during sin,cos calculations
|
||
|
// use m_nPhase/2
|
||
|
|
||
|
int16_t m_nPhaseIncrement; // add this to m_nPhase each frame
|
||
|
|
||
|
int16_t m_nNoise; // random noise sample
|
||
|
|
||
|
uint16_t m_nMaxExcursion; // the taps can excurse +/- this amount
|
||
|
|
||
|
uint16_t m_bUseNoise; // if TRUE, use noise as input signal
|
||
|
|
||
|
uint16_t m_bBypass; // if TRUE, then bypass reverb and copy input to output
|
||
|
|
||
|
int16_t m_nCurrentRoom; // preset number for current room
|
||
|
|
||
|
int16_t m_nNextRoom; // preset number for next room
|
||
|
|
||
|
int16_t m_nEarlyGain; // gain for early (widen) signal
|
||
|
int16_t m_nEarlyDelay; // initial dealy for early (widen) signal
|
||
|
int16_t m_nEarly0in;
|
||
|
int16_t m_nEarly1in;
|
||
|
int16_t m_nLateGain; // gain for late reverb
|
||
|
int16_t m_nLateDelay;
|
||
|
|
||
|
int16_t m_nDiffusion;
|
||
|
|
||
|
early_reflection_object_t m_sEarlyL; // left channel early reflections
|
||
|
early_reflection_object_t m_sEarlyR; // right channel early reflections
|
||
|
|
||
|
short m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX]; // one large delay line for all reverb elements
|
||
|
|
||
|
reverb_preset_t pPreset;
|
||
|
|
||
|
reverb_preset_bank_t m_sPreset;
|
||
|
|
||
|
//int8_t preset;
|
||
|
uint32_t m_nSamplingRate;
|
||
|
int32_t m_nUpdatePeriodInBits;
|
||
|
int32_t m_nBufferMask;
|
||
|
int32_t m_nUpdatePeriodInSamples;
|
||
|
int32_t m_nDelay0Out;
|
||
|
int32_t m_nDelay1Out;
|
||
|
int16_t m_nCosWT_5KHz;
|
||
|
|
||
|
uint16_t m_Aux; // if TRUE, is connected as auxiliary effect
|
||
|
uint16_t m_Preset; // if TRUE, expose preset revert interface
|
||
|
|
||
|
uint32_t mState;
|
||
|
} reverb_object_t;
|
||
|
|
||
|
|
||
|
|
||
|
typedef struct reverb_module_s {
|
||
|
const struct effect_interface_s *itfe;
|
||
|
effect_config_t config;
|
||
|
reverb_object_t context;
|
||
|
} reverb_module_t;
|
||
|
|
||
|
/*------------------------------------
|
||
|
* Effect API
|
||
|
*------------------------------------
|
||
|
*/
|
||
|
int EffectQueryNumberEffects(uint32_t *pNumEffects);
|
||
|
int EffectQueryEffect(uint32_t index,
|
||
|
effect_descriptor_t *pDescriptor);
|
||
|
int EffectCreate(effect_uuid_t *effectUID,
|
||
|
int32_t sessionId,
|
||
|
int32_t ioId,
|
||
|
effect_interface_t *pInterface);
|
||
|
int EffectRelease(effect_interface_t interface);
|
||
|
|
||
|
static int Reverb_Process(effect_interface_t self,
|
||
|
audio_buffer_t *inBuffer,
|
||
|
audio_buffer_t *outBuffer);
|
||
|
static int Reverb_Command(effect_interface_t self,
|
||
|
uint32_t cmdCode,
|
||
|
uint32_t cmdSize,
|
||
|
void *pCmdData,
|
||
|
uint32_t *replySize,
|
||
|
void *pReplyData);
|
||
|
|
||
|
|
||
|
/*------------------------------------
|
||
|
* internal functions
|
||
|
*------------------------------------
|
||
|
*/
|
||
|
|
||
|
int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset);
|
||
|
int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init);
|
||
|
void Reverb_Reset(reverb_object_t *pReverb, bool init);
|
||
|
|
||
|
int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue);
|
||
|
int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue);
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* ReverbUpdateXfade
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose:
|
||
|
* Update the xfade parameters as required
|
||
|
*
|
||
|
* Inputs:
|
||
|
* nNumSamplesToAdd - number of samples to write to buffer
|
||
|
*
|
||
|
* Outputs:
|
||
|
*
|
||
|
*
|
||
|
* Side Effects:
|
||
|
* - xfade parameters will be changed
|
||
|
*
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd);
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* ReverbCalculateNoise
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose:
|
||
|
* Calculate a noise sample and limit its value
|
||
|
*
|
||
|
* Inputs:
|
||
|
* Pointer to reverb context
|
||
|
*
|
||
|
* Outputs:
|
||
|
* new limited noise value
|
||
|
*
|
||
|
* Side Effects:
|
||
|
* - pReverbData->m_nNoise value is updated
|
||
|
*
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData);
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* ReverbCalculateSinCos
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose:
|
||
|
* Calculate a new sin and cosine value based on the given phase
|
||
|
*
|
||
|
* Inputs:
|
||
|
* nPhase - phase angle
|
||
|
* pnSin - input old value, output new value
|
||
|
* pnCos - input old value, output new value
|
||
|
*
|
||
|
* Outputs:
|
||
|
*
|
||
|
* Side Effects:
|
||
|
* - *pnSin, *pnCos are updated
|
||
|
*
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos);
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* Reverb
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose:
|
||
|
* apply reverb to the given signal
|
||
|
*
|
||
|
* Inputs:
|
||
|
* nNu
|
||
|
* pnSin - input old value, output new value
|
||
|
* pnCos - input old value, output new value
|
||
|
*
|
||
|
* Outputs:
|
||
|
* number of samples actually reverberated
|
||
|
*
|
||
|
* Side Effects:
|
||
|
*
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer);
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* ReverbReadInPresets()
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose: sets global reverb preset bank to defaults
|
||
|
*
|
||
|
* Inputs:
|
||
|
*
|
||
|
* Outputs:
|
||
|
*
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static int ReverbReadInPresets(reverb_object_t* pReverbData);
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------------
|
||
|
* ReverbUpdateRoom
|
||
|
*----------------------------------------------------------------------------
|
||
|
* Purpose:
|
||
|
* Update the room's preset parameters as required
|
||
|
*
|
||
|
* Inputs:
|
||
|
*
|
||
|
* Outputs:
|
||
|
*
|
||
|
*
|
||
|
* Side Effects:
|
||
|
* - reverb paramters (fbk, fwd, etc) will be changed
|
||
|
* - m_nCurrentRoom := m_nNextRoom
|
||
|
*----------------------------------------------------------------------------
|
||
|
*/
|
||
|
static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate);
|
||
|
|
||
|
|
||
|
static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate);
|
||
|
|
||
|
#endif /*ANDROID_EFFECTREVERB_H_*/
|