| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1 | /* //device/include/server/AudioFlinger/AudioMixer.h | 
 | 2 | ** | 
 | 3 | ** Copyright 2007, The Android Open Source Project | 
 | 4 | ** | 
 | 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 | ** you may not use this file except in compliance with the License. | 
 | 7 | ** You may obtain a copy of the License at | 
 | 8 | ** | 
 | 9 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 | ** | 
 | 11 | ** Unless required by applicable law or agreed to in writing, software | 
 | 12 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 | ** See the License for the specific language governing permissions and | 
 | 15 | ** limitations under the License. | 
 | 16 | */ | 
 | 17 |  | 
 | 18 | #ifndef ANDROID_AUDIO_MIXER_H | 
 | 19 | #define ANDROID_AUDIO_MIXER_H | 
 | 20 |  | 
 | 21 | #include <stdint.h> | 
 | 22 | #include <sys/types.h> | 
 | 23 |  | 
 | 24 | #include "AudioBufferProvider.h" | 
 | 25 | #include "AudioResampler.h" | 
 | 26 |  | 
 | 27 | namespace android { | 
 | 28 |  | 
 | 29 | // ---------------------------------------------------------------------------- | 
 | 30 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 31 | class AudioMixer | 
 | 32 | { | 
 | 33 | public: | 
 | 34 |                             AudioMixer(size_t frameCount, uint32_t sampleRate); | 
 | 35 |  | 
 | 36 |                             ~AudioMixer(); | 
 | 37 |  | 
 | 38 |     static const uint32_t MAX_NUM_TRACKS = 32; | 
 | 39 |     static const uint32_t MAX_NUM_CHANNELS = 2; | 
 | 40 |  | 
 | 41 |     static const uint16_t UNITY_GAIN = 0x1000; | 
 | 42 |  | 
 | 43 |     enum { // names | 
 | 44 |  | 
| Glenn Kasten | bf71f1e | 2011-12-13 11:52:35 -0800 | [diff] [blame] | 45 |         // track units (MAX_NUM_TRACKS units) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 46 |         TRACK0          = 0x1000, | 
 | 47 |  | 
| Glenn Kasten | 1c48c3c | 2011-12-15 14:54:01 -0800 | [diff] [blame] | 48 |         // 0x2000 is unused | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 49 |  | 
 | 50 |         // setParameter targets | 
 | 51 |         TRACK           = 0x3000, | 
 | 52 |         RESAMPLE        = 0x3001, | 
 | 53 |         RAMP_VOLUME     = 0x3002, // ramp to new volume | 
 | 54 |         VOLUME          = 0x3003, // don't ramp | 
 | 55 |  | 
 | 56 |         // set Parameter names | 
 | 57 |         // for target TRACK | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 58 |         CHANNEL_MASK    = 0x4000, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 59 |         FORMAT          = 0x4001, | 
 | 60 |         MAIN_BUFFER     = 0x4002, | 
 | 61 |         AUX_BUFFER      = 0x4003, | 
| Glenn Kasten | 362c4e6 | 2011-12-14 10:28:06 -0800 | [diff] [blame] | 62 |         // for target RESAMPLE | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 63 |         SAMPLE_RATE     = 0x4100, | 
| Eric Laurent | 243f5f9 | 2011-02-28 16:52:51 -0800 | [diff] [blame] | 64 |         RESET           = 0x4101, | 
| Glenn Kasten | 362c4e6 | 2011-12-14 10:28:06 -0800 | [diff] [blame] | 65 |         // for target RAMP_VOLUME and VOLUME (8 channels max) | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 66 |         VOLUME0         = 0x4200, | 
 | 67 |         VOLUME1         = 0x4201, | 
 | 68 |         AUXLEVEL        = 0x4210, | 
 | 69 |     }; | 
 | 70 |  | 
 | 71 |  | 
 | 72 |     int         getTrackName(); | 
 | 73 |     void        deleteTrackName(int name); | 
 | 74 |  | 
| Glenn Kasten | 1c48c3c | 2011-12-15 14:54:01 -0800 | [diff] [blame] | 75 |     void        enable(); | 
 | 76 |     void        disable(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 77 |  | 
| Glenn Kasten | fba380a | 2011-12-15 15:46:46 -0800 | [diff] [blame] | 78 |     void        setActiveTrack(int track); | 
| Glenn Kasten | 788040c | 2011-05-05 08:19:00 -0700 | [diff] [blame] | 79 |     void        setParameter(int target, int name, void *value); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 80 |  | 
| Glenn Kasten | fba380a | 2011-12-15 15:46:46 -0800 | [diff] [blame] | 81 |     void        setBufferProvider(AudioBufferProvider* bufferProvider); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 82 |     void        process(); | 
 | 83 |  | 
 | 84 |     uint32_t    trackNames() const { return mTrackNames; } | 
 | 85 |  | 
| Eric Laurent | 071ccd5 | 2011-12-22 16:08:41 -0800 | [diff] [blame] | 86 |     size_t      getUnreleasedFrames(int name); | 
 | 87 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 88 | private: | 
 | 89 |  | 
 | 90 |     enum { | 
 | 91 |         NEEDS_CHANNEL_COUNT__MASK   = 0x00000003, | 
 | 92 |         NEEDS_FORMAT__MASK          = 0x000000F0, | 
 | 93 |         NEEDS_MUTE__MASK            = 0x00000100, | 
 | 94 |         NEEDS_RESAMPLE__MASK        = 0x00001000, | 
 | 95 |         NEEDS_AUX__MASK             = 0x00010000, | 
 | 96 |     }; | 
 | 97 |  | 
 | 98 |     enum { | 
 | 99 |         NEEDS_CHANNEL_1             = 0x00000000, | 
 | 100 |         NEEDS_CHANNEL_2             = 0x00000001, | 
 | 101 |  | 
 | 102 |         NEEDS_FORMAT_16             = 0x00000010, | 
 | 103 |  | 
 | 104 |         NEEDS_MUTE_DISABLED         = 0x00000000, | 
 | 105 |         NEEDS_MUTE_ENABLED          = 0x00000100, | 
 | 106 |  | 
 | 107 |         NEEDS_RESAMPLE_DISABLED     = 0x00000000, | 
 | 108 |         NEEDS_RESAMPLE_ENABLED      = 0x00001000, | 
 | 109 |  | 
 | 110 |         NEEDS_AUX_DISABLED     = 0x00000000, | 
 | 111 |         NEEDS_AUX_ENABLED      = 0x00010000, | 
 | 112 |     }; | 
 | 113 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 114 |     struct state_t; | 
 | 115 |     struct track_t; | 
 | 116 |  | 
 | 117 |     typedef void (*mix_t)(state_t* state); | 
 | 118 |     typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux); | 
 | 119 |     static const int BLOCKSIZE = 16; // 4 cache lines | 
 | 120 |  | 
 | 121 |     struct track_t { | 
 | 122 |         uint32_t    needs; | 
 | 123 |  | 
 | 124 |         union { | 
| Glenn Kasten | bf71f1e | 2011-12-13 11:52:35 -0800 | [diff] [blame] | 125 |         int16_t     volume[MAX_NUM_CHANNELS]; // [0]3.12 fixed point | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 126 |         int32_t     volumeRL; | 
 | 127 |         }; | 
 | 128 |  | 
| Glenn Kasten | bf71f1e | 2011-12-13 11:52:35 -0800 | [diff] [blame] | 129 |         int32_t     prevVolume[MAX_NUM_CHANNELS]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 130 |  | 
| Glenn Kasten | bf71f1e | 2011-12-13 11:52:35 -0800 | [diff] [blame] | 131 |         int32_t     volumeInc[MAX_NUM_CHANNELS]; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 132 |         int32_t     auxLevel; | 
 | 133 |         int32_t     auxInc; | 
 | 134 |         int32_t     prevAuxLevel; | 
 | 135 |  | 
 | 136 |         uint16_t    frameCount; | 
 | 137 |  | 
 | 138 |         uint8_t     channelCount : 4; | 
 | 139 |         uint8_t     enabled      : 1; | 
 | 140 |         uint8_t     reserved0    : 3; | 
 | 141 |         uint8_t     format; | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 142 |         uint32_t    channelMask; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 143 |  | 
 | 144 |         AudioBufferProvider*                bufferProvider; | 
 | 145 |         mutable AudioBufferProvider::Buffer buffer; | 
 | 146 |  | 
 | 147 |         hook_t      hook; | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame^] | 148 |         const void* in;             // current location in buffer | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 149 |  | 
 | 150 |         AudioResampler*     resampler; | 
 | 151 |         uint32_t            sampleRate; | 
 | 152 |         int32_t*           mainBuffer; | 
 | 153 |         int32_t*           auxBuffer; | 
 | 154 |  | 
 | 155 |         bool        setResampler(uint32_t sampleRate, uint32_t devSampleRate); | 
 | 156 |         bool        doesResample() const; | 
| Eric Laurent | 243f5f9 | 2011-02-28 16:52:51 -0800 | [diff] [blame] | 157 |         void        resetResampler(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 158 |         void        adjustVolumeRamp(bool aux); | 
| Eric Laurent | 071ccd5 | 2011-12-22 16:08:41 -0800 | [diff] [blame] | 159 |         size_t      getUnreleasedFrames(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 160 |     }; | 
 | 161 |  | 
 | 162 |     // pad to 32-bytes to fill cache line | 
 | 163 |     struct state_t { | 
 | 164 |         uint32_t        enabledTracks; | 
 | 165 |         uint32_t        needsChanged; | 
 | 166 |         size_t          frameCount; | 
 | 167 |         mix_t           hook; | 
 | 168 |         int32_t         *outputTemp; | 
 | 169 |         int32_t         *resampleTemp; | 
 | 170 |         int32_t         reserved[2]; | 
| Glenn Kasten | bf71f1e | 2011-12-13 11:52:35 -0800 | [diff] [blame] | 171 |         track_t         tracks[MAX_NUM_TRACKS]; __attribute__((aligned(32))); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 172 |     }; | 
 | 173 |  | 
 | 174 |     int             mActiveTrack; | 
 | 175 |     uint32_t        mTrackNames; | 
 | 176 |     const uint32_t  mSampleRate; | 
 | 177 |  | 
 | 178 |     state_t         mState __attribute__((aligned(32))); | 
 | 179 |  | 
 | 180 |     void invalidateState(uint32_t mask); | 
 | 181 |  | 
 | 182 |     static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux); | 
 | 183 |     static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux); | 
 | 184 |     static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux); | 
 | 185 |     static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux); | 
 | 186 |     static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux); | 
 | 187 |     static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux); | 
 | 188 |  | 
 | 189 |     static void process__validate(state_t* state); | 
 | 190 |     static void process__nop(state_t* state); | 
 | 191 |     static void process__genericNoResampling(state_t* state); | 
 | 192 |     static void process__genericResampling(state_t* state); | 
 | 193 |     static void process__OneTrack16BitsStereoNoResampling(state_t* state); | 
| Glenn Kasten | 81a028f | 2011-12-15 09:53:12 -0800 | [diff] [blame] | 194 | #if 0 | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 195 |     static void process__TwoTracks16BitsStereoNoResampling(state_t* state); | 
| Glenn Kasten | 81a028f | 2011-12-15 09:53:12 -0800 | [diff] [blame] | 196 | #endif | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 197 | }; | 
 | 198 |  | 
 | 199 | // ---------------------------------------------------------------------------- | 
 | 200 | }; // namespace android | 
 | 201 |  | 
 | 202 | #endif // ANDROID_AUDIO_MIXER_H |