199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten/* 265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Copyright 2007, The Android Open Source Project 465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Licensed under the Apache License, Version 2.0 (the "License"); 665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** you may not use this file except in compliance with the License. 765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** You may obtain a copy of the License at 865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** http://www.apache.org/licenses/LICENSE-2.0 1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** 1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** Unless required by applicable law or agreed to in writing, software 1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** distributed under the License is distributed on an "AS IS" BASIS, 1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** See the License for the specific language governing permissions and 1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian** limitations under the License. 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian*/ 1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#ifndef ANDROID_AUDIO_MIXER_H 1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define ANDROID_AUDIO_MIXER_H 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <stdint.h> 2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/types.h> 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 247d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi#include <utils/threads.h> 257d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi 262dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/AudioBufferProvider.h> 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioResampler.h" 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 299a59276fb465e492138e0576523b54079671e8f4Andy Hung#include <hardware/audio_effect.h> 307d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi#include <system/audio.h> 31ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten#include <media/nbaio/NBLog.h> 327d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi 33c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten// FIXME This is actually unity gain, which might not be max in future, expressed in U.12 3497ae82408469286426d8dc57a361350f74e24a8bAndy Hung#define MAX_GAIN_INT AudioMixer::UNITY_GAIN_INT 35c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianclass AudioMixer 4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{ 4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianpublic: 435c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten AudioMixer(size_t frameCount, uint32_t sampleRate, 445c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten uint32_t maxNumTracks = MAX_NUM_TRACKS); 4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 46c19e22450e6e3d07594c935c7a9522e85e909e82Glenn Kasten /*virtual*/ ~AudioMixer(); // non-virtual saves a v-table, restore if sub-classed 4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 48599fabc596687efa4b71b8f3ebbb957c7cae0c72Glenn Kasten 49599fabc596687efa4b71b8f3ebbb957c7cae0c72Glenn Kasten // This mixer has a hard-coded upper limit of 32 active track inputs. 50599fabc596687efa4b71b8f3ebbb957c7cae0c72Glenn Kasten // Adding support for > 32 tracks would require more than simply changing this value. 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static const uint32_t MAX_NUM_TRACKS = 32; 527d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi // maximum number of channels supported by the mixer 53599fabc596687efa4b71b8f3ebbb957c7cae0c72Glenn Kasten 54e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung // This mixer has a hard-coded upper limit of 8 channels for output. 55e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static const uint32_t MAX_NUM_CHANNELS = 8; 56e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static const uint32_t MAX_NUM_VOLUMES = 2; // stereo volume only 577d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi // maximum number of channels supported for the content 58e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static const uint32_t MAX_NUM_CHANNELS_TO_DOWNMIX = AUDIO_CHANNEL_COUNT_MAX; 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6097ae82408469286426d8dc57a361350f74e24a8bAndy Hung static const uint16_t UNITY_GAIN_INT = 0x1000; 616be494077f8d7970f3a88129c5d139c5a0c88f6dAndy Hung static const float UNITY_GAIN_FLOAT = 1.0f; 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian enum { // names 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 659c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten // track names (MAX_NUM_TRACKS units) 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian TRACK0 = 0x1000, 6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 681c48c3c61970527b97892ab6a2daae8eaac26964Glenn Kasten // 0x2000 is unused 6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // setParameter targets 7165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian TRACK = 0x3000, 7265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian RESAMPLE = 0x3001, 7365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian RAMP_VOLUME = 0x3002, // ramp to new volume 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian VOLUME = 0x3003, // don't ramp 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // set Parameter names 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // for target TRACK 780d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi CHANNEL_MASK = 0x4000, 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian FORMAT = 0x4001, 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian MAIN_BUFFER = 0x4002, 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AUX_BUFFER = 0x4003, 827d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi DOWNMIX_TYPE = 0X4004, 83788207057ed4b8df4719ed8089f376ef52de9ca1Andy Hung MIXER_FORMAT = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT) 84e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output 85362c4e697d8e9c034e964ac7b40227e054491547Glenn Kasten // for target RESAMPLE 864e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten SAMPLE_RATE = 0x4100, // Configure sample rate conversion on this track name; 874e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // parameter 'value' is the new sample rate in Hz. 884e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // Only creates a sample rate converter the first time that 894e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // the track sample rate is different from the mix sample rate. 904e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // If the new sample rate is the same as the mix sample rate, 914e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // and a sample rate converter already exists, 924e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // then the sample rate converter remains present but is a no-op. 934e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten RESET = 0x4101, // Reset sample rate converter without changing sample rate. 944e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // This clears out the resampler's input buffer. 954e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten REMOVE = 0x4102, // Remove the sample rate converter on this track name; 964e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // the track is restored to the mix sample rate. 97362c4e697d8e9c034e964ac7b40227e054491547Glenn Kasten // for target RAMP_VOLUME and VOLUME (8 channels max) 98c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten // FIXME use float for these 3 to improve the dynamic range 9965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian VOLUME0 = 0x4200, 10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian VOLUME1 = 0x4201, 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AUXLEVEL = 0x4210, 10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 10365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1059c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten // For all APIs with "name": TRACK0 <= name < TRACK0 + MAX_NUM_TRACKS 10617a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten 10717a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten // Allocate a track name. Returns new track name if successful, -1 on failure. 108e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung // The failure could be because of an invalid channelMask or format, or that 109e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung // the track capacity of the mixer is exceeded. 110e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung int getTrackName(audio_channel_mask_t channelMask, 111e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung audio_format_t format, int sessionId); 11217a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten 11317a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten // Free an allocated track by name 11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void deleteTrackName(int name); 11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 11617a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten // Enable or disable an allocated track by name 1179c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten void enable(int name); 1189c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten void disable(int name); 11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1209c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten void setParameter(int name, int target, int param, void *value); 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1229c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten void setBufferProvider(int name, AudioBufferProvider* bufferProvider); 1234ff14bae91075eb274eb1c2975982358946e7e63John Grossman void process(int64_t pts); 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t trackNames() const { return mTrackNames; } 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 127c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten size_t getUnreleasedFrames(int name) const; 128071ccd5a9702500f3f7d62ef881300914926184dEric Laurent 129e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung static inline bool isValidPcmTrackFormat(audio_format_t format) { 130ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung return format == AUDIO_FORMAT_PCM_16_BIT || 131ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung format == AUDIO_FORMAT_PCM_24_BIT_PACKED || 132ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung format == AUDIO_FORMAT_PCM_32_BIT || 133ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung format == AUDIO_FORMAT_PCM_FLOAT; 134e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung } 135e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung 13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianprivate: 13765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian enum { 139d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten // FIXME this representation permits up to 8 channels 1407d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi NEEDS_CHANNEL_COUNT__MASK = 0x00000007, 14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian enum { 144d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten NEEDS_CHANNEL_1 = 0x00000000, // mono 145d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten NEEDS_CHANNEL_2 = 0x00000001, // stereo 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 147d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten // sample format is not explicitly specified, and is assumed to be AUDIO_FORMAT_PCM_16_BIT 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 149d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten NEEDS_MUTE = 0x00000100, 150d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten NEEDS_RESAMPLE = 0x00001000, 151d6fadf0479b489b09b764070974d8a59855ede64Glenn Kasten NEEDS_AUX = 0x00010000, 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 15365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct state_t; 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct track_t; 1561b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung class CopyBufferProvider; 15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15885ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, 15985ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static const int BLOCKSIZE = 16; // 4 cache lines 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct track_t { 16365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t needs; 16465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1655e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung // TODO: Eventually remove legacy integer volume settings 16665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian union { 167e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung int16_t volume[MAX_NUM_VOLUMES]; // U4.12 fixed point (top bit should be zero) 16865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t volumeRL; 16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 17065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 171e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung int32_t prevVolume[MAX_NUM_VOLUMES]; 17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1733b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 1743b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 175e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung int32_t volumeInc[MAX_NUM_VOLUMES]; 17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t auxInc; 17765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t prevAuxLevel; 17865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1793b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 1803b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 1813b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten int16_t auxLevel; // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance 18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint16_t frameCount; 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1843b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten uint8_t channelCount; // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK) 185ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung uint8_t unused_padding; // formerly format, was always 16 1863b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten uint16_t enabled; // actually bool 1877d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi audio_channel_mask_t channelMask; 18865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1897d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi // actual buffer provider used by the track hooks, see DownmixerBufferProvider below 1907d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi // for how the Track buffer provider is wrapped by another one when dowmixing is required 19165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* bufferProvider; 1923b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 1933b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 1943b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 1953b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten mutable AudioBufferProvider::Buffer buffer; // 8 bytes 19665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 19765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian hook_t hook; 19854c3b66444ebfb9f2265ee70ac3b76ccefa0506aGlenn Kasten const void* in; // current location in buffer 19965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2003b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 2013b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 20265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioResampler* resampler; 20365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t sampleRate; 20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t* mainBuffer; 20565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t* auxBuffer; 20665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2073b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 2081b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider. 2091b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung CopyBufferProvider* mReformatBufferProvider; // provider wrapper for reformatting. 21034803d594232af5604d893eff7ee40bb57d459a4Andy Hung CopyBufferProvider* downmixerBufferProvider; // wrapper for channel conversion. 2117d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi 212d06e132358d44f02c22527b4f463df1f58da9216Jean-Michel Trivi int32_t sessionId; 213d06e132358d44f02c22527b4f463df1f58da9216Jean-Michel Trivi 214ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung // 16-byte boundary 215e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung audio_format_t mMixerFormat; // output mix format: AUDIO_FORMAT_PCM_(FLOAT|16_BIT) 216e8a1ced4da17dc6c07803dc2af8060f62a8389c1Andy Hung audio_format_t mFormat; // input track format 217ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung audio_format_t mMixerInFormat; // mix internal format AUDIO_FORMAT_PCM_(FLOAT|16_BIT) 218ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung // each track must be converted to this format. 219ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung 220e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung float mVolume[MAX_NUM_VOLUMES]; // floating point set volume 221e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung float mPrevVolume[MAX_NUM_VOLUMES]; // floating point previous volume 222e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung float mVolumeInc[MAX_NUM_VOLUMES]; // floating point volume increment 2235e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 2245e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung float mAuxLevel; // floating point set aux level 2255e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung float mPrevAuxLevel; // floating point prev aux level 2265e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung float mAuxInc; // floating point aux increment 2273b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 2283b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten // 16-byte boundary 229e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung audio_channel_mask_t mMixerChannelMask; 230e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung uint32_t mMixerChannelCount; 2313b81acab52b7140c1b8b20be2d67be3e221637e7Glenn Kasten 232296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung bool needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; } 233e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung bool setResampler(uint32_t trackSampleRate, uint32_t devSampleRate); 234c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten bool doesResample() const { return resampler != NULL; } 235c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten void resetResampler() { if (resampler != NULL) resampler->reset(); } 2365e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung void adjustVolumeRamp(bool aux, bool useFloat = false); 237c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten size_t getUnreleasedFrames() const { return resampler != NULL ? 238c59c004a3a6042c0990d71179f88eee2ce781e3cGlenn Kasten resampler->getUnreleasedFrames() : 0; }; 23965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 24065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 241296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung typedef void (*process_hook_t)(state_t* state, int64_t pts); 242296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 24365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // pad to 32-bytes to fill cache line 24465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian struct state_t { 24565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t enabledTracks; 24665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t needsChanged; 24765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t frameCount; 248296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung process_hook_t hook; // one of process__*, never NULL 24965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t *outputTemp; 25065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t *resampleTemp; 251ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten NBLog::Writer* mLog; 252ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten int32_t reserved[1]; 2535c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten // FIXME allocate dynamically to save some memory when maxNumTracks < MAX_NUM_TRACKS 25401d3acba9de861cb2b718338e787cff3566fc5ecGlenn Kasten track_t tracks[MAX_NUM_TRACKS] __attribute__((aligned(32))); 25565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian }; 25665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 257a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung // Base AudioBufferProvider class used for DownMixerBufferProvider, RemixBufferProvider, 258a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung // and ReformatBufferProvider. 2591b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // It handles a private buffer for use in converting format or channel masks from the 2601b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // input data to a form acceptable by the mixer. 2611b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // TODO: Make a ResamplerBufferProvider when integers are entirely removed from the 2621b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // processing pipeline. 2631b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung class CopyBufferProvider : public AudioBufferProvider { 2641b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung public: 2651b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // Use a private buffer of bufferFrameCount frames (each frame is outputFrameSize bytes). 2661b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // If bufferFrameCount is 0, no private buffer is created and in-place modification of 2671b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // the upstream buffer provider's buffers is performed by copyFrames(). 2681b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung CopyBufferProvider(size_t inputFrameSize, size_t outputFrameSize, 2691b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung size_t bufferFrameCount); 2701b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual ~CopyBufferProvider(); 2711b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2721b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // Overrides AudioBufferProvider methods 2731b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual status_t getNextBuffer(Buffer* buffer, int64_t pts); 2741b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual void releaseBuffer(Buffer* buffer); 2751b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2761b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // Other public methods 2771b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2781b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // call this to release the buffer to the upstream provider. 2791b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // treat it as an audio discontinuity for future samples. 2801b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual void reset(); 2811b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2821b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // this function should be supplied by the derived class. It converts 2831b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // #frames in the *src pointer to the *dst pointer. It is public because 2841b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // some providers will allow this to work on arbitrary buffers outside 2851b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // of the internal buffers. 2861b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual void copyFrames(void *dst, const void *src, size_t frames) = 0; 2871b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2881b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // set the upstream buffer provider. Consider calling "reset" before this function. 2891b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung void setBufferProvider(AudioBufferProvider *p) { 2901b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung mTrackBufferProvider = p; 2911b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung } 2921b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 2931b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung protected: 2941b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung AudioBufferProvider* mTrackBufferProvider; 2951b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const size_t mInputFrameSize; 2961b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const size_t mOutputFrameSize; 2971b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung private: 2981b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung AudioBufferProvider::Buffer mBuffer; 2991b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const size_t mLocalBufferFrameCount; 3001b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung void* mLocalBufferData; 3011b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung size_t mConsumed; 3021b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung }; 3031b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 30434803d594232af5604d893eff7ee40bb57d459a4Andy Hung // DownmixerBufferProvider wraps a track AudioBufferProvider to provide 30534803d594232af5604d893eff7ee40bb57d459a4Andy Hung // position dependent downmixing by an Audio Effect. 30634803d594232af5604d893eff7ee40bb57d459a4Andy Hung class DownmixerBufferProvider : public CopyBufferProvider { 3077d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi public: 30834803d594232af5604d893eff7ee40bb57d459a4Andy Hung DownmixerBufferProvider(audio_channel_mask_t inputChannelMask, 30934803d594232af5604d893eff7ee40bb57d459a4Andy Hung audio_channel_mask_t outputChannelMask, audio_format_t format, 31034803d594232af5604d893eff7ee40bb57d459a4Andy Hung uint32_t sampleRate, int32_t sessionId, size_t bufferFrameCount); 3117d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi virtual ~DownmixerBufferProvider(); 31234803d594232af5604d893eff7ee40bb57d459a4Andy Hung virtual void copyFrames(void *dst, const void *src, size_t frames); 31334803d594232af5604d893eff7ee40bb57d459a4Andy Hung bool isValid() const { return mDownmixHandle != NULL; } 3147d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi 31534803d594232af5604d893eff7ee40bb57d459a4Andy Hung static status_t init(); 31634803d594232af5604d893eff7ee40bb57d459a4Andy Hung static bool isMultichannelCapable() { return sIsMultichannelCapable; } 31734803d594232af5604d893eff7ee40bb57d459a4Andy Hung 31834803d594232af5604d893eff7ee40bb57d459a4Andy Hung protected: 3197d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi effect_handle_t mDownmixHandle; 3207d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi effect_config_t mDownmixConfig; 32134803d594232af5604d893eff7ee40bb57d459a4Andy Hung 32234803d594232af5604d893eff7ee40bb57d459a4Andy Hung // effect descriptor for the downmixer used by the mixer 32334803d594232af5604d893eff7ee40bb57d459a4Andy Hung static effect_descriptor_t sDwnmFxDesc; 32434803d594232af5604d893eff7ee40bb57d459a4Andy Hung // indicates whether a downmix effect has been found and is usable by this mixer 32534803d594232af5604d893eff7ee40bb57d459a4Andy Hung static bool sIsMultichannelCapable; 32634803d594232af5604d893eff7ee40bb57d459a4Andy Hung // FIXME: should we allow effects outside of the framework? 32734803d594232af5604d893eff7ee40bb57d459a4Andy Hung // We need to here. A special ioId that must be <= -2 so it does not map to a session. 32834803d594232af5604d893eff7ee40bb57d459a4Andy Hung static const int32_t SESSION_ID_INVALID_AND_IGNORED = -2; 3297d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi }; 3307d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi 331a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung // RemixBufferProvider wraps a track AudioBufferProvider to perform an 332a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung // upmix or downmix to the proper channel count and mask. 333a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung class RemixBufferProvider : public CopyBufferProvider { 334a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung public: 335a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung RemixBufferProvider(audio_channel_mask_t inputChannelMask, 336a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung audio_channel_mask_t outputChannelMask, audio_format_t format, 337a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung size_t bufferFrameCount); 338a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung virtual void copyFrames(void *dst, const void *src, size_t frames); 339a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung 340a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung protected: 341a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung const audio_format_t mFormat; 342a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung const size_t mSampleSize; 343a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung const size_t mInputChannels; 344a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung const size_t mOutputChannels; 345a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung int8_t mIdxAry[sizeof(uint32_t)*8]; // 32 bits => channel indices 346a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung }; 347a08810b2feafeec88870c7c1f01efc39ee8e0d78Andy Hung 3481b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // ReformatBufferProvider wraps a track AudioBufferProvider to convert the input data 3491b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung // to an acceptable mixer input format type. 3501b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung class ReformatBufferProvider : public CopyBufferProvider { 351ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung public: 352ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung ReformatBufferProvider(int32_t channels, 3531b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung audio_format_t inputFormat, audio_format_t outputFormat, 3541b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung size_t bufferFrameCount); 3551b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung virtual void copyFrames(void *dst, const void *src, size_t frames); 3561b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung 3571b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung protected: 3581b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const int32_t mChannels; 3591b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const audio_format_t mInputFormat; 3601b2fdcb005f9fbe5ad465cec46ec5992b718b5e3Andy Hung const audio_format_t mOutputFormat; 361ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung }; 362ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung 3639c56d4ae6212c21ce5fd71ed534eb195983a07c1Glenn Kasten // bitmask of allocated track names, where bit 0 corresponds to TRACK0 etc. 36465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t mTrackNames; 3655c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten 3665c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten // bitmask of configured track names; ~0 if maxNumTracks == MAX_NUM_TRACKS, 3675c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten // but will have fewer bits set if maxNumTracks < MAX_NUM_TRACKS 3685c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten const uint32_t mConfiguredNames; 3695c94b6c7689a335e26a86e8a0d04b56dc627738eGlenn Kasten 37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian const uint32_t mSampleRate; 37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 372ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten NBLog::Writer mDummyLog; 373ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kastenpublic: 374ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kasten void setLog(NBLog::Writer* log); 375ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0Glenn Kastenprivate: 37665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian state_t mState __attribute__((aligned(32))); 37765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3784e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // Call after changing either the enabled status of a track, or parameters of an enabled track. 3794e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten // OK to call more often than that, but unnecessary. 38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian void invalidateState(uint32_t mask); 3814e2293f29f2e719af1245d365747ea06d074b345Glenn Kasten 382e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung bool setChannelMasks(int name, 383e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung audio_channel_mask_t trackChannelMask, audio_channel_mask_t mixerChannelMask); 384e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung 385e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung // TODO: remove unused trackName/trackNum from functions below. 386e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static status_t initTrackDownmix(track_t* pTrack, int trackName); 3877d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi static status_t prepareTrackForDownmix(track_t* pTrack, int trackNum); 3889bd23229fdec1657398abc682ccccfce1c95f8aaJean-Michel Trivi static void unprepareTrackForDownmix(track_t* pTrack, int trackName); 389ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung static status_t prepareTrackForReformat(track_t* pTrack, int trackNum); 390ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung static void unprepareTrackForReformat(track_t* pTrack, int trackName); 391ef7c7fbd0e3fb36af14cd7d39f64c949031516a5Andy Hung static void reconfigureBufferProviders(track_t* pTrack); 39265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 39385ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, 39485ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux); 39685ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, 39785ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 39885ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, 39985ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 40085ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, 40185ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 40285ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, 40385ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten int32_t* aux); 40465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 4054ff14bae91075eb274eb1c2975982358946e7e63John Grossman static void process__validate(state_t* state, int64_t pts); 4064ff14bae91075eb274eb1c2975982358946e7e63John Grossman static void process__nop(state_t* state, int64_t pts); 4074ff14bae91075eb274eb1c2975982358946e7e63John Grossman static void process__genericNoResampling(state_t* state, int64_t pts); 4084ff14bae91075eb274eb1c2975982358946e7e63John Grossman static void process__genericResampling(state_t* state, int64_t pts); 4094ff14bae91075eb274eb1c2975982358946e7e63John Grossman static void process__OneTrack16BitsStereoNoResampling(state_t* state, 4104ff14bae91075eb274eb1c2975982358946e7e63John Grossman int64_t pts); 4114ff14bae91075eb274eb1c2975982358946e7e63John Grossman 4124ff14bae91075eb274eb1c2975982358946e7e63John Grossman static int64_t calculateOutputPTS(const track_t& t, int64_t basePTS, 4134ff14bae91075eb274eb1c2975982358946e7e63John Grossman int outputFrameIndex); 41452008f821a5202502a82a8ba2c024e69bd336350Glenn Kasten 41552008f821a5202502a82a8ba2c024e69bd336350Glenn Kasten static uint64_t sLocalTimeFreq; 41652008f821a5202502a82a8ba2c024e69bd336350Glenn Kasten static pthread_once_t sOnceControl; 41752008f821a5202502a82a8ba2c024e69bd336350Glenn Kasten static void sInitRoutine(); 418296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 4195e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung /* multi-format volume mixing function (calls template functions 4205e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * in AudioMixerOps.h). The template parameters are as follows: 4215e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * 4225e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration) 4235e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * USEFLOATVOL (set to true if float volume is used) 4245e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * ADJUSTVOL (set to true if volume ramp parameters needs adjustment afterwards) 4255e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * TO: int32_t (Q4.27) or float 4265e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * TI: int32_t (Q4.27) or int16_t (Q0.15) or float 4275e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung * TA: int32_t (Q4.27) 4285e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung */ 429e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung template <int MIXTYPE, bool USEFLOATVOL, bool ADJUSTVOL, 4305e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung typename TO, typename TI, typename TA> 4315e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung static void volumeMix(TO *out, size_t outFrames, 4325e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung const TI *in, TA *aux, bool ramp, AudioMixer::track_t *t); 4335e58b0abe5b6c8f5bd96a8f78bbeeeb4d3892020Andy Hung 434296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // multi-format process hooks 435e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung template <int MIXTYPE, typename TO, typename TI, typename TA> 436296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static void process_NoResampleOneTrack(state_t* state, int64_t pts); 437296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 438296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // multi-format track hooks 439e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung template <int MIXTYPE, typename TO, typename TI, typename TA> 440296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static void track__Resample(track_t* t, TO* out, size_t frameCount, 441296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TO* temp __unused, TA* aux); 442e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung template <int MIXTYPE, typename TO, typename TI, typename TA> 443296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static void track__NoResample(track_t* t, TO* out, size_t frameCount, 444296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TO* temp __unused, TA* aux); 445296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 446296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung static void convertMixerFormat(void *out, audio_format_t mixerOutFormat, 447296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung void *in, audio_format_t mixerInFormat, size_t sampleCount); 448296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 449296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // hook types 450296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung enum { 451296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung PROCESSTYPE_NORESAMPLEONETRACK, 452296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung }; 453296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung enum { 454296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TRACKTYPE_NOP, 455296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TRACKTYPE_RESAMPLE, 456296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TRACKTYPE_NORESAMPLE, 457296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung TRACKTYPE_NORESAMPLEMONO, 458296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung }; 459296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung 460296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung // functions for determining the proper process and track hooks. 461e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static process_hook_t getProcessHook(int processType, uint32_t channelCount, 462296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung audio_format_t mixerInFormat, audio_format_t mixerOutFormat); 463e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung static hook_t getTrackHook(int trackType, uint32_t channelCount, 464296b741e8eb38e749e3202182f703a2e30ee5f1fAndy Hung audio_format_t mixerInFormat, audio_format_t mixerOutFormat); 46565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; 46665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 46765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 46865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}; // namespace android 46965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 47065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#endif // ANDROID_AUDIO_MIXER_H 471