eafff459aa
First drop of audio framework modifications for audio effects support. - AudioTrack/AudioRecord: Added support for auxiliary effects in AudioTrack Added support for audio sessions Fixed left right channel inversion in setVolume() - IAudioFlinger: Added interface methods for effect enumeraiton and instantiation Added support for audio sessions. - IAudioTrack: Added method to attach auxiliary effect. - AudioFlinger Created new classes to control effect engines in effect library and manage effect connections to tracks or output mix: EffectModule: wrapper object controlling the effect engine implementation in the effect library. There is one EffectModule per instance of an effect in a given audio session EffectChain: group of effects associated to one audio session. There is one EffectChain per audio session. EffectChain for session 0 is for output mix effects, other chains are attached to audio tracks with same session ID. Each chain contains a variable number of EffectModules EffectHandle: implements the IEffect interface. There is one EffectHandle object for each application controlling (or using) an effect module. THe EffectModule maintians a list of EffectHandles. Added support for effect modules and effect chains creation in PlaybackThread. modified mixer thread loop to allow track volume control by effect modules and call effect processing. -AudioMixer Each track now specifies its output buffer used by mixer for accumulation Modified mixer process functions to process tracks by groups of tracks with same buffer Modified track process functions to support accumulation to auxiliary channel Change-Id: I26d5f7c9e070a89bdd383e1a659f8b7ca150379c
208 lines
6.4 KiB
C++
208 lines
6.4 KiB
C++
/* //device/include/server/AudioFlinger/AudioMixer.h
|
|
**
|
|
** Copyright 2007, 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_AUDIO_MIXER_H
|
|
#define ANDROID_AUDIO_MIXER_H
|
|
|
|
#include <stdint.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "AudioBufferProvider.h"
|
|
#include "AudioResampler.h"
|
|
|
|
namespace android {
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
|
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class AudioMixer
|
|
{
|
|
public:
|
|
AudioMixer(size_t frameCount, uint32_t sampleRate);
|
|
|
|
~AudioMixer();
|
|
|
|
static const uint32_t MAX_NUM_TRACKS = 32;
|
|
static const uint32_t MAX_NUM_CHANNELS = 2;
|
|
|
|
static const uint16_t UNITY_GAIN = 0x1000;
|
|
|
|
enum { // names
|
|
|
|
// track units (32 units)
|
|
TRACK0 = 0x1000,
|
|
|
|
// enable/disable
|
|
MIXING = 0x2000,
|
|
|
|
// setParameter targets
|
|
TRACK = 0x3000,
|
|
RESAMPLE = 0x3001,
|
|
RAMP_VOLUME = 0x3002, // ramp to new volume
|
|
VOLUME = 0x3003, // don't ramp
|
|
|
|
// set Parameter names
|
|
// for target TRACK
|
|
CHANNEL_COUNT = 0x4000,
|
|
FORMAT = 0x4001,
|
|
MAIN_BUFFER = 0x4002,
|
|
AUX_BUFFER = 0x4003,
|
|
// for TARGET RESAMPLE
|
|
SAMPLE_RATE = 0x4100,
|
|
// for TARGET VOLUME (8 channels max)
|
|
VOLUME0 = 0x4200,
|
|
VOLUME1 = 0x4201,
|
|
AUXLEVEL = 0x4210,
|
|
};
|
|
|
|
|
|
int getTrackName();
|
|
void deleteTrackName(int name);
|
|
|
|
status_t enable(int name);
|
|
status_t disable(int name);
|
|
|
|
status_t setActiveTrack(int track);
|
|
status_t setParameter(int target, int name, void *value);
|
|
|
|
status_t setBufferProvider(AudioBufferProvider* bufferProvider);
|
|
void process();
|
|
|
|
uint32_t trackNames() const { return mTrackNames; }
|
|
|
|
static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
|
|
|
|
private:
|
|
|
|
enum {
|
|
NEEDS_CHANNEL_COUNT__MASK = 0x00000003,
|
|
NEEDS_FORMAT__MASK = 0x000000F0,
|
|
NEEDS_MUTE__MASK = 0x00000100,
|
|
NEEDS_RESAMPLE__MASK = 0x00001000,
|
|
NEEDS_AUX__MASK = 0x00010000,
|
|
};
|
|
|
|
enum {
|
|
NEEDS_CHANNEL_1 = 0x00000000,
|
|
NEEDS_CHANNEL_2 = 0x00000001,
|
|
|
|
NEEDS_FORMAT_16 = 0x00000010,
|
|
|
|
NEEDS_MUTE_DISABLED = 0x00000000,
|
|
NEEDS_MUTE_ENABLED = 0x00000100,
|
|
|
|
NEEDS_RESAMPLE_DISABLED = 0x00000000,
|
|
NEEDS_RESAMPLE_ENABLED = 0x00001000,
|
|
|
|
NEEDS_AUX_DISABLED = 0x00000000,
|
|
NEEDS_AUX_ENABLED = 0x00010000,
|
|
};
|
|
|
|
static inline int32_t applyVolume(int32_t in, int32_t v) {
|
|
return in * v;
|
|
}
|
|
|
|
|
|
struct state_t;
|
|
struct track_t;
|
|
|
|
typedef void (*mix_t)(state_t* state);
|
|
typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
|
|
static const int BLOCKSIZE = 16; // 4 cache lines
|
|
|
|
struct track_t {
|
|
uint32_t needs;
|
|
|
|
union {
|
|
int16_t volume[2]; // [0]3.12 fixed point
|
|
int32_t volumeRL;
|
|
};
|
|
|
|
int32_t prevVolume[2];
|
|
|
|
int32_t volumeInc[2];
|
|
int32_t auxLevel;
|
|
int32_t auxInc;
|
|
int32_t prevAuxLevel;
|
|
|
|
uint16_t frameCount;
|
|
|
|
uint8_t channelCount : 4;
|
|
uint8_t enabled : 1;
|
|
uint8_t reserved0 : 3;
|
|
uint8_t format;
|
|
|
|
AudioBufferProvider* bufferProvider;
|
|
mutable AudioBufferProvider::Buffer buffer;
|
|
|
|
hook_t hook;
|
|
void const* in; // current location in buffer
|
|
|
|
AudioResampler* resampler;
|
|
uint32_t sampleRate;
|
|
int32_t* mainBuffer;
|
|
int32_t* auxBuffer;
|
|
|
|
bool setResampler(uint32_t sampleRate, uint32_t devSampleRate);
|
|
bool doesResample() const;
|
|
void adjustVolumeRamp(bool aux);
|
|
};
|
|
|
|
// pad to 32-bytes to fill cache line
|
|
struct state_t {
|
|
uint32_t enabledTracks;
|
|
uint32_t needsChanged;
|
|
size_t frameCount;
|
|
mix_t hook;
|
|
int32_t *outputTemp;
|
|
int32_t *resampleTemp;
|
|
int32_t reserved[2];
|
|
track_t tracks[32]; __attribute__((aligned(32)));
|
|
};
|
|
|
|
int mActiveTrack;
|
|
uint32_t mTrackNames;
|
|
const uint32_t mSampleRate;
|
|
|
|
state_t mState __attribute__((aligned(32)));
|
|
|
|
void invalidateState(uint32_t mask);
|
|
|
|
static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
|
static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
|
static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
|
static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
|
|
static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
|
|
static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
|
|
|
|
static void process__validate(state_t* state);
|
|
static void process__nop(state_t* state);
|
|
static void process__genericNoResampling(state_t* state);
|
|
static void process__genericResampling(state_t* state);
|
|
static void process__OneTrack16BitsStereoNoResampling(state_t* state);
|
|
static void process__TwoTracks16BitsStereoNoResampling(state_t* state);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_AUDIO_MIXER_H
|