xref: /aosp_15_r20/frameworks/av/media/libaudioprocessing/tests/test-mixer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <stdio.h>
18*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <math.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <vector>
21*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/primitives.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/sndfile.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioBufferProvider.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioMixer.h>
25*ec779b8eSAndroid Build Coastguard Worker #include "test_utils.h"
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker /* Testing is typically through creation of an output WAV file from several
28*ec779b8eSAndroid Build Coastguard Worker  * source inputs, to be later analyzed by an audio program such as Audacity.
29*ec779b8eSAndroid Build Coastguard Worker  *
30*ec779b8eSAndroid Build Coastguard Worker  * Sine or chirp functions are typically more useful as input to the mixer
31*ec779b8eSAndroid Build Coastguard Worker  * as they show up as straight lines on a spectrogram if successfully mixed.
32*ec779b8eSAndroid Build Coastguard Worker  *
33*ec779b8eSAndroid Build Coastguard Worker  * A sample shell script is provided: mixer_to_wave_tests.sh
34*ec779b8eSAndroid Build Coastguard Worker  */
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker using namespace android;
37*ec779b8eSAndroid Build Coastguard Worker 
usage(const char * name)38*ec779b8eSAndroid Build Coastguard Worker static void usage(const char* name) {
39*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "Usage: %s [-f] [-m] [-c channels]"
40*ec779b8eSAndroid Build Coastguard Worker                     " [-s sample-rate] [-o <output-file>] [-a <aux-buffer-file>] [-P csv]"
41*ec779b8eSAndroid Build Coastguard Worker                     " (<input-file> | <command>)+\n", name);
42*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -f    enable floating point input track by default\n");
43*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -m    enable floating point mixer output\n");
44*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -c    number of mixer output channels\n");
45*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -s    mixer sample-rate\n");
46*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -o    <output-file> WAV file, pcm16 (or float if -m specified)\n");
47*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -a    <aux-buffer-file>\n");
48*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    -P    # frames provided per call to resample() in CSV format\n");
49*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    <input-file> is a WAV file\n");
50*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "    <command> can be 'sine:[(i|f),]<channels>,<frequency>,<samplerate>'\n");
51*ec779b8eSAndroid Build Coastguard Worker     fprintf(stderr, "                     'chirp:[(i|f),]<channels>,<samplerate>'\n");
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker 
writeFile(const char * filename,const void * buffer,uint32_t sampleRate,uint32_t channels,size_t frames,bool isBufferFloat)54*ec779b8eSAndroid Build Coastguard Worker static int writeFile(const char *filename, const void *buffer,
55*ec779b8eSAndroid Build Coastguard Worker         uint32_t sampleRate, uint32_t channels, size_t frames, bool isBufferFloat) {
56*ec779b8eSAndroid Build Coastguard Worker     if (filename == NULL) {
57*ec779b8eSAndroid Build Coastguard Worker         return 0; // ok to pass in NULL filename
58*ec779b8eSAndroid Build Coastguard Worker     }
59*ec779b8eSAndroid Build Coastguard Worker     // write output to file.
60*ec779b8eSAndroid Build Coastguard Worker     SF_INFO info;
61*ec779b8eSAndroid Build Coastguard Worker     info.frames = 0;
62*ec779b8eSAndroid Build Coastguard Worker     info.samplerate = sampleRate;
63*ec779b8eSAndroid Build Coastguard Worker     info.channels = channels;
64*ec779b8eSAndroid Build Coastguard Worker     info.format = SF_FORMAT_WAV | (isBufferFloat ? SF_FORMAT_FLOAT : SF_FORMAT_PCM_16);
65*ec779b8eSAndroid Build Coastguard Worker     printf("saving file:%s  channels:%u  samplerate:%u  frames:%zu\n",
66*ec779b8eSAndroid Build Coastguard Worker             filename, info.channels, info.samplerate, frames);
67*ec779b8eSAndroid Build Coastguard Worker     SNDFILE *sf = sf_open(filename, SFM_WRITE, &info);
68*ec779b8eSAndroid Build Coastguard Worker     if (sf == NULL) {
69*ec779b8eSAndroid Build Coastguard Worker         perror(filename);
70*ec779b8eSAndroid Build Coastguard Worker         return EXIT_FAILURE;
71*ec779b8eSAndroid Build Coastguard Worker     }
72*ec779b8eSAndroid Build Coastguard Worker     if (isBufferFloat) {
73*ec779b8eSAndroid Build Coastguard Worker         (void) sf_writef_float(sf, (float*)buffer, frames);
74*ec779b8eSAndroid Build Coastguard Worker     } else {
75*ec779b8eSAndroid Build Coastguard Worker         (void) sf_writef_short(sf, (short*)buffer, frames);
76*ec779b8eSAndroid Build Coastguard Worker     }
77*ec779b8eSAndroid Build Coastguard Worker     sf_close(sf);
78*ec779b8eSAndroid Build Coastguard Worker     return EXIT_SUCCESS;
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker 
parseFormat(const char * s,bool * useFloat)81*ec779b8eSAndroid Build Coastguard Worker const char *parseFormat(const char *s, bool *useFloat) {
82*ec779b8eSAndroid Build Coastguard Worker     if (!strncmp(s, "f,", 2)) {
83*ec779b8eSAndroid Build Coastguard Worker         *useFloat = true;
84*ec779b8eSAndroid Build Coastguard Worker         return s + 2;
85*ec779b8eSAndroid Build Coastguard Worker     }
86*ec779b8eSAndroid Build Coastguard Worker     if (!strncmp(s, "i,", 2)) {
87*ec779b8eSAndroid Build Coastguard Worker         *useFloat = false;
88*ec779b8eSAndroid Build Coastguard Worker         return s + 2;
89*ec779b8eSAndroid Build Coastguard Worker     }
90*ec779b8eSAndroid Build Coastguard Worker     return s;
91*ec779b8eSAndroid Build Coastguard Worker }
92*ec779b8eSAndroid Build Coastguard Worker 
main(int argc,char * argv[])93*ec779b8eSAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
94*ec779b8eSAndroid Build Coastguard Worker     const char* const progname = argv[0];
95*ec779b8eSAndroid Build Coastguard Worker     bool useInputFloat = false;
96*ec779b8eSAndroid Build Coastguard Worker     bool useMixerFloat = false;
97*ec779b8eSAndroid Build Coastguard Worker     bool useRamp = true;
98*ec779b8eSAndroid Build Coastguard Worker     uint32_t outputSampleRate = 48000;
99*ec779b8eSAndroid Build Coastguard Worker     uint32_t outputChannels = 2; // stereo for now
100*ec779b8eSAndroid Build Coastguard Worker     std::vector<int> Pvalues;
101*ec779b8eSAndroid Build Coastguard Worker     const char* outputFilename = NULL;
102*ec779b8eSAndroid Build Coastguard Worker     const char* auxFilename = NULL;
103*ec779b8eSAndroid Build Coastguard Worker     std::vector<int32_t> names;
104*ec779b8eSAndroid Build Coastguard Worker     std::vector<SignalProvider> providers;
105*ec779b8eSAndroid Build Coastguard Worker     std::vector<audio_format_t> formats;
106*ec779b8eSAndroid Build Coastguard Worker 
107*ec779b8eSAndroid Build Coastguard Worker     for (int ch; (ch = getopt(argc, argv, "fmc:s:o:a:P:")) != -1;) {
108*ec779b8eSAndroid Build Coastguard Worker         switch (ch) {
109*ec779b8eSAndroid Build Coastguard Worker         case 'f':
110*ec779b8eSAndroid Build Coastguard Worker             useInputFloat = true;
111*ec779b8eSAndroid Build Coastguard Worker             break;
112*ec779b8eSAndroid Build Coastguard Worker         case 'm':
113*ec779b8eSAndroid Build Coastguard Worker             useMixerFloat = true;
114*ec779b8eSAndroid Build Coastguard Worker             break;
115*ec779b8eSAndroid Build Coastguard Worker         case 'c':
116*ec779b8eSAndroid Build Coastguard Worker             outputChannels = atoi(optarg);
117*ec779b8eSAndroid Build Coastguard Worker             break;
118*ec779b8eSAndroid Build Coastguard Worker         case 's':
119*ec779b8eSAndroid Build Coastguard Worker             outputSampleRate = atoi(optarg);
120*ec779b8eSAndroid Build Coastguard Worker             break;
121*ec779b8eSAndroid Build Coastguard Worker         case 'o':
122*ec779b8eSAndroid Build Coastguard Worker             outputFilename = optarg;
123*ec779b8eSAndroid Build Coastguard Worker             break;
124*ec779b8eSAndroid Build Coastguard Worker         case 'a':
125*ec779b8eSAndroid Build Coastguard Worker             auxFilename = optarg;
126*ec779b8eSAndroid Build Coastguard Worker             break;
127*ec779b8eSAndroid Build Coastguard Worker         case 'P':
128*ec779b8eSAndroid Build Coastguard Worker             if (parseCSV(optarg, Pvalues) < 0) {
129*ec779b8eSAndroid Build Coastguard Worker                 fprintf(stderr, "incorrect syntax for -P option\n");
130*ec779b8eSAndroid Build Coastguard Worker                 return EXIT_FAILURE;
131*ec779b8eSAndroid Build Coastguard Worker             }
132*ec779b8eSAndroid Build Coastguard Worker             break;
133*ec779b8eSAndroid Build Coastguard Worker         case '?':
134*ec779b8eSAndroid Build Coastguard Worker         default:
135*ec779b8eSAndroid Build Coastguard Worker             usage(progname);
136*ec779b8eSAndroid Build Coastguard Worker             return EXIT_FAILURE;
137*ec779b8eSAndroid Build Coastguard Worker         }
138*ec779b8eSAndroid Build Coastguard Worker     }
139*ec779b8eSAndroid Build Coastguard Worker     argc -= optind;
140*ec779b8eSAndroid Build Coastguard Worker     argv += optind;
141*ec779b8eSAndroid Build Coastguard Worker 
142*ec779b8eSAndroid Build Coastguard Worker     if (argc == 0) {
143*ec779b8eSAndroid Build Coastguard Worker         usage(progname);
144*ec779b8eSAndroid Build Coastguard Worker         return EXIT_FAILURE;
145*ec779b8eSAndroid Build Coastguard Worker     }
146*ec779b8eSAndroid Build Coastguard Worker 
147*ec779b8eSAndroid Build Coastguard Worker     size_t outputFrames = 0;
148*ec779b8eSAndroid Build Coastguard Worker 
149*ec779b8eSAndroid Build Coastguard Worker     // create providers for each track
150*ec779b8eSAndroid Build Coastguard Worker     names.resize(argc);
151*ec779b8eSAndroid Build Coastguard Worker     providers.resize(argc);
152*ec779b8eSAndroid Build Coastguard Worker     formats.resize(argc);
153*ec779b8eSAndroid Build Coastguard Worker     for (int i = 0; i < argc; ++i) {
154*ec779b8eSAndroid Build Coastguard Worker         static const char chirp[] = "chirp:";
155*ec779b8eSAndroid Build Coastguard Worker         static const char sine[] = "sine:";
156*ec779b8eSAndroid Build Coastguard Worker         static const double kSeconds = 1;
157*ec779b8eSAndroid Build Coastguard Worker         bool useFloat = useInputFloat;
158*ec779b8eSAndroid Build Coastguard Worker 
159*ec779b8eSAndroid Build Coastguard Worker         if (!strncmp(argv[i], chirp, strlen(chirp))) {
160*ec779b8eSAndroid Build Coastguard Worker             std::vector<int> v;
161*ec779b8eSAndroid Build Coastguard Worker             const char *s = parseFormat(argv[i] + strlen(chirp), &useFloat);
162*ec779b8eSAndroid Build Coastguard Worker 
163*ec779b8eSAndroid Build Coastguard Worker             parseCSV(s, v);
164*ec779b8eSAndroid Build Coastguard Worker             if (v.size() == 2) {
165*ec779b8eSAndroid Build Coastguard Worker                 printf("creating chirp(%d %d)\n", v[0], v[1]);
166*ec779b8eSAndroid Build Coastguard Worker                 if (useFloat) {
167*ec779b8eSAndroid Build Coastguard Worker                     providers[i].setChirp<float>(v[0], 0, v[1]/2, v[1], kSeconds);
168*ec779b8eSAndroid Build Coastguard Worker                     formats[i] = AUDIO_FORMAT_PCM_FLOAT;
169*ec779b8eSAndroid Build Coastguard Worker                 } else {
170*ec779b8eSAndroid Build Coastguard Worker                     providers[i].setChirp<int16_t>(v[0], 0, v[1]/2, v[1], kSeconds);
171*ec779b8eSAndroid Build Coastguard Worker                     formats[i] = AUDIO_FORMAT_PCM_16_BIT;
172*ec779b8eSAndroid Build Coastguard Worker                 }
173*ec779b8eSAndroid Build Coastguard Worker                 providers[i].setIncr(Pvalues);
174*ec779b8eSAndroid Build Coastguard Worker             } else {
175*ec779b8eSAndroid Build Coastguard Worker                 fprintf(stderr, "malformed input '%s'\n", argv[i]);
176*ec779b8eSAndroid Build Coastguard Worker             }
177*ec779b8eSAndroid Build Coastguard Worker         } else if (!strncmp(argv[i], sine, strlen(sine))) {
178*ec779b8eSAndroid Build Coastguard Worker             std::vector<int> v;
179*ec779b8eSAndroid Build Coastguard Worker             const char *s = parseFormat(argv[i] + strlen(sine), &useFloat);
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker             parseCSV(s, v);
182*ec779b8eSAndroid Build Coastguard Worker             if (v.size() == 3) {
183*ec779b8eSAndroid Build Coastguard Worker                 printf("creating sine(%d %d %d)\n", v[0], v[1], v[2]);
184*ec779b8eSAndroid Build Coastguard Worker                 if (useFloat) {
185*ec779b8eSAndroid Build Coastguard Worker                     providers[i].setSine<float>(v[0], v[1], v[2], kSeconds);
186*ec779b8eSAndroid Build Coastguard Worker                     formats[i] = AUDIO_FORMAT_PCM_FLOAT;
187*ec779b8eSAndroid Build Coastguard Worker                 } else {
188*ec779b8eSAndroid Build Coastguard Worker                     providers[i].setSine<int16_t>(v[0], v[1], v[2], kSeconds);
189*ec779b8eSAndroid Build Coastguard Worker                     formats[i] = AUDIO_FORMAT_PCM_16_BIT;
190*ec779b8eSAndroid Build Coastguard Worker                 }
191*ec779b8eSAndroid Build Coastguard Worker                 providers[i].setIncr(Pvalues);
192*ec779b8eSAndroid Build Coastguard Worker             } else {
193*ec779b8eSAndroid Build Coastguard Worker                 fprintf(stderr, "malformed input '%s'\n", argv[i]);
194*ec779b8eSAndroid Build Coastguard Worker             }
195*ec779b8eSAndroid Build Coastguard Worker         } else {
196*ec779b8eSAndroid Build Coastguard Worker             printf("creating filename(%s)\n", argv[i]);
197*ec779b8eSAndroid Build Coastguard Worker             if (useInputFloat) {
198*ec779b8eSAndroid Build Coastguard Worker                 providers[i].setFile<float>(argv[i]);
199*ec779b8eSAndroid Build Coastguard Worker                 formats[i] = AUDIO_FORMAT_PCM_FLOAT;
200*ec779b8eSAndroid Build Coastguard Worker             } else {
201*ec779b8eSAndroid Build Coastguard Worker                 providers[i].setFile<short>(argv[i]);
202*ec779b8eSAndroid Build Coastguard Worker                 formats[i] = AUDIO_FORMAT_PCM_16_BIT;
203*ec779b8eSAndroid Build Coastguard Worker             }
204*ec779b8eSAndroid Build Coastguard Worker             providers[i].setIncr(Pvalues);
205*ec779b8eSAndroid Build Coastguard Worker         }
206*ec779b8eSAndroid Build Coastguard Worker         // calculate the number of output frames
207*ec779b8eSAndroid Build Coastguard Worker         size_t nframes = (int64_t) providers[i].getNumFrames() * outputSampleRate
208*ec779b8eSAndroid Build Coastguard Worker                 / providers[i].getSampleRate();
209*ec779b8eSAndroid Build Coastguard Worker         if (i == 0 || outputFrames > nframes) { // choose minimum for outputFrames
210*ec779b8eSAndroid Build Coastguard Worker             outputFrames = nframes;
211*ec779b8eSAndroid Build Coastguard Worker         }
212*ec779b8eSAndroid Build Coastguard Worker     }
213*ec779b8eSAndroid Build Coastguard Worker 
214*ec779b8eSAndroid Build Coastguard Worker     // create the output buffer.
215*ec779b8eSAndroid Build Coastguard Worker     const size_t outputFrameSize = outputChannels
216*ec779b8eSAndroid Build Coastguard Worker             * (useMixerFloat ? sizeof(float) : sizeof(int16_t));
217*ec779b8eSAndroid Build Coastguard Worker     const size_t outputSize = outputFrames * outputFrameSize;
218*ec779b8eSAndroid Build Coastguard Worker     const audio_channel_mask_t outputChannelMask =
219*ec779b8eSAndroid Build Coastguard Worker             audio_channel_out_mask_from_count(outputChannels);
220*ec779b8eSAndroid Build Coastguard Worker     void *outputAddr = NULL;
221*ec779b8eSAndroid Build Coastguard Worker     (void) posix_memalign(&outputAddr, 32, outputSize);
222*ec779b8eSAndroid Build Coastguard Worker     memset(outputAddr, 0, outputSize);
223*ec779b8eSAndroid Build Coastguard Worker 
224*ec779b8eSAndroid Build Coastguard Worker     // create the aux buffer, if needed.
225*ec779b8eSAndroid Build Coastguard Worker     const size_t auxFrameSize = sizeof(int32_t); // Q4.27 always
226*ec779b8eSAndroid Build Coastguard Worker     const size_t auxSize = outputFrames * auxFrameSize;
227*ec779b8eSAndroid Build Coastguard Worker     void *auxAddr = NULL;
228*ec779b8eSAndroid Build Coastguard Worker     if (auxFilename) {
229*ec779b8eSAndroid Build Coastguard Worker         (void) posix_memalign(&auxAddr, 32, auxSize);
230*ec779b8eSAndroid Build Coastguard Worker         memset(auxAddr, 0, auxSize);
231*ec779b8eSAndroid Build Coastguard Worker     }
232*ec779b8eSAndroid Build Coastguard Worker 
233*ec779b8eSAndroid Build Coastguard Worker     // create the mixer.
234*ec779b8eSAndroid Build Coastguard Worker     const size_t mixerFrameCount = 320; // typical numbers may range from 240 or 960
235*ec779b8eSAndroid Build Coastguard Worker     AudioMixer *mixer = new AudioMixer(mixerFrameCount, outputSampleRate);
236*ec779b8eSAndroid Build Coastguard Worker     audio_format_t mixerFormat = useMixerFloat
237*ec779b8eSAndroid Build Coastguard Worker             ? AUDIO_FORMAT_PCM_FLOAT : AUDIO_FORMAT_PCM_16_BIT;
238*ec779b8eSAndroid Build Coastguard Worker     float f = AudioMixer::UNITY_GAIN_FLOAT / providers.size(); // normalize volume by # tracks
239*ec779b8eSAndroid Build Coastguard Worker     static float f0; // zero
240*ec779b8eSAndroid Build Coastguard Worker 
241*ec779b8eSAndroid Build Coastguard Worker     // set up the tracks.
242*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < providers.size(); ++i) {
243*ec779b8eSAndroid Build Coastguard Worker         //printf("track %d out of %d\n", i, providers.size());
244*ec779b8eSAndroid Build Coastguard Worker         audio_channel_mask_t channelMask =
245*ec779b8eSAndroid Build Coastguard Worker                 audio_channel_out_mask_from_count(providers[i].getNumChannels());
246*ec779b8eSAndroid Build Coastguard Worker         const int name = i;
247*ec779b8eSAndroid Build Coastguard Worker         const status_t status = mixer->create(
248*ec779b8eSAndroid Build Coastguard Worker                 name, channelMask, formats[i], AUDIO_SESSION_OUTPUT_MIX);
249*ec779b8eSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(status != OK);
250*ec779b8eSAndroid Build Coastguard Worker         names[i] = name;
251*ec779b8eSAndroid Build Coastguard Worker         mixer->setBufferProvider(name, &providers[i]);
252*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
253*ec779b8eSAndroid Build Coastguard Worker                 (void *)outputAddr);
254*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(
255*ec779b8eSAndroid Build Coastguard Worker                 name,
256*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::TRACK,
257*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::MIXER_FORMAT,
258*ec779b8eSAndroid Build Coastguard Worker                 (void *)(uintptr_t)mixerFormat);
259*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(
260*ec779b8eSAndroid Build Coastguard Worker                 name,
261*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::TRACK,
262*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::FORMAT,
263*ec779b8eSAndroid Build Coastguard Worker                 (void *)(uintptr_t)formats[i]);
264*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(
265*ec779b8eSAndroid Build Coastguard Worker                 name,
266*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::TRACK,
267*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::MIXER_CHANNEL_MASK,
268*ec779b8eSAndroid Build Coastguard Worker                 (void *)(uintptr_t)outputChannelMask);
269*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(
270*ec779b8eSAndroid Build Coastguard Worker                 name,
271*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::TRACK,
272*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::CHANNEL_MASK,
273*ec779b8eSAndroid Build Coastguard Worker                 (void *)(uintptr_t)channelMask);
274*ec779b8eSAndroid Build Coastguard Worker         mixer->setParameter(
275*ec779b8eSAndroid Build Coastguard Worker                 name,
276*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::RESAMPLE,
277*ec779b8eSAndroid Build Coastguard Worker                 AudioMixer::SAMPLE_RATE,
278*ec779b8eSAndroid Build Coastguard Worker                 (void *)(uintptr_t)providers[i].getSampleRate());
279*ec779b8eSAndroid Build Coastguard Worker         if (useRamp) {
280*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f0);
281*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f0);
282*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME0, &f);
283*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::VOLUME1, &f);
284*ec779b8eSAndroid Build Coastguard Worker         } else {
285*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &f);
286*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &f);
287*ec779b8eSAndroid Build Coastguard Worker         }
288*ec779b8eSAndroid Build Coastguard Worker         if (auxFilename) {
289*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::AUX_BUFFER,
290*ec779b8eSAndroid Build Coastguard Worker                     (void *) auxAddr);
291*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::AUXLEVEL, &f0);
292*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(name, AudioMixer::RAMP_VOLUME, AudioMixer::AUXLEVEL, &f);
293*ec779b8eSAndroid Build Coastguard Worker         }
294*ec779b8eSAndroid Build Coastguard Worker         mixer->enable(name);
295*ec779b8eSAndroid Build Coastguard Worker     }
296*ec779b8eSAndroid Build Coastguard Worker 
297*ec779b8eSAndroid Build Coastguard Worker     // pump the mixer to process data.
298*ec779b8eSAndroid Build Coastguard Worker     size_t i;
299*ec779b8eSAndroid Build Coastguard Worker     for (i = 0; i < outputFrames - mixerFrameCount; i += mixerFrameCount) {
300*ec779b8eSAndroid Build Coastguard Worker         for (size_t j = 0; j < names.size(); ++j) {
301*ec779b8eSAndroid Build Coastguard Worker             mixer->setParameter(names[j], AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
302*ec779b8eSAndroid Build Coastguard Worker                     (char *) outputAddr + i * outputFrameSize);
303*ec779b8eSAndroid Build Coastguard Worker             if (auxFilename) {
304*ec779b8eSAndroid Build Coastguard Worker                 mixer->setParameter(names[j], AudioMixer::TRACK, AudioMixer::AUX_BUFFER,
305*ec779b8eSAndroid Build Coastguard Worker                         (char *) auxAddr + i * auxFrameSize);
306*ec779b8eSAndroid Build Coastguard Worker             }
307*ec779b8eSAndroid Build Coastguard Worker         }
308*ec779b8eSAndroid Build Coastguard Worker         mixer->process();
309*ec779b8eSAndroid Build Coastguard Worker     }
310*ec779b8eSAndroid Build Coastguard Worker     outputFrames = i; // reset output frames to the data actually produced.
311*ec779b8eSAndroid Build Coastguard Worker 
312*ec779b8eSAndroid Build Coastguard Worker     // write to files
313*ec779b8eSAndroid Build Coastguard Worker     writeFile(outputFilename, outputAddr,
314*ec779b8eSAndroid Build Coastguard Worker             outputSampleRate, outputChannels, outputFrames, useMixerFloat);
315*ec779b8eSAndroid Build Coastguard Worker     if (auxFilename) {
316*ec779b8eSAndroid Build Coastguard Worker         // Aux buffer is always in q4_27 format for O and earlier.
317*ec779b8eSAndroid Build Coastguard Worker         // memcpy_to_i16_from_q4_27((int16_t*)auxAddr, (const int32_t*)auxAddr, outputFrames);
318*ec779b8eSAndroid Build Coastguard Worker         // Aux buffer is always in float format for P.
319*ec779b8eSAndroid Build Coastguard Worker         memcpy_to_i16_from_float((int16_t*)auxAddr, (const float*)auxAddr, outputFrames);
320*ec779b8eSAndroid Build Coastguard Worker         writeFile(auxFilename, auxAddr, outputSampleRate, 1, outputFrames, false);
321*ec779b8eSAndroid Build Coastguard Worker     }
322*ec779b8eSAndroid Build Coastguard Worker 
323*ec779b8eSAndroid Build Coastguard Worker     delete mixer;
324*ec779b8eSAndroid Build Coastguard Worker     free(outputAddr);
325*ec779b8eSAndroid Build Coastguard Worker     free(auxAddr);
326*ec779b8eSAndroid Build Coastguard Worker     return EXIT_SUCCESS;
327*ec779b8eSAndroid Build Coastguard Worker }
328