18dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk/*
28dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * Copyright (C) 2017 The Android Open Source Project
38dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk *
48dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * Licensed under the Apache License, Version 2.0 (the "License");
58dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * you may not use this file except in compliance with the License.
68dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * You may obtain a copy of the License at
78dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk *
88dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk *      http://www.apache.org/licenses/LICENSE-2.0
98dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk *
108dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * Unless required by applicable law or agreed to in writing, software
118dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * distributed under the License is distributed on an "AS IS" BASIS,
128dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * See the License for the specific language governing permissions and
148dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk * limitations under the License.
158dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk */
168dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
178dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk// Play sine waves using AAudio.
188dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
198dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk#include <stdio.h>
208dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk//#include <stdlib.h>
218dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk//#include <math.h>
228dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
238dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk#include <android-base/macros.h>
248dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk#include <aaudio/AAudio.h>
258dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
268dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk#include <gtest/gtest.h>
278dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
288dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burkstatic const char *getSharingModeText(aaudio_sharing_mode_t mode) {
298dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    const char *modeText = "unknown";
308dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    switch (mode) {
318dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    case AAUDIO_SHARING_MODE_EXCLUSIVE:
328dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        modeText = "EXCLUSIVE";
338dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        break;
348dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    case AAUDIO_SHARING_MODE_SHARED:
358dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        modeText = "SHARED";
368dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        break;
378dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    default:
388dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        break;
398dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
408dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    return modeText;
418dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk}
428dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
438dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk// Callback function that fills the audio output buffer.
448dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burkaaudio_data_callback_result_t MyDataCallbackProc(
458dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        AAudioStream *stream,
468dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        void *userData,
478dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        void *audioData,
488dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        int32_t numFrames
498dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk) {
508dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    (void) stream;
518dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    (void) userData;
528dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    (void) audioData;
538dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    (void) numFrames;
548dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    return AAUDIO_CALLBACK_RESULT_CONTINUE;
558dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk}
568dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
578dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burkstatic void testOpenOptions(aaudio_direction_t direction,
588dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk                            int32_t channelCount,
598dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk                            int32_t sampleRate,
609dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk                            aaudio_format_t format) {
618dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
628dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    aaudio_result_t result = AAUDIO_OK;
638dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
648dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    int32_t bufferCapacity;
658dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    int32_t framesPerBurst = 0;
668dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
678dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    int32_t actualChannelCount = 0;
688dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    int32_t actualSampleRate = 0;
699dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk    aaudio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
708dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
718dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    aaudio_direction_t actualDirection;
728dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
738dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder *aaudioBuilder = nullptr;
748dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStream *aaudioStream = nullptr;
758dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
768dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    printf("TestOpen: dir = %d, chans = %3d, rate = %6d format = %d\n",
778dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk           direction, channelCount, sampleRate, format);
788dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
798dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // Use an AAudioStreamBuilder to contain requested parameters.
808dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
818dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
828dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // Request stream properties.
838dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
848dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setSampleRate(aaudioBuilder, sampleRate);
858dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setChannelCount(aaudioBuilder, channelCount);
868dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setFormat(aaudioBuilder, format);
878dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setDataCallback(aaudioBuilder, MyDataCallbackProc, nullptr);
888dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
898dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_NONE);
908dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
918dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    //AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
928dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
938dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // Create an AAudioStream using the Builder.
948dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
958dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    if (result != AAUDIO_OK) {
968dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        printf("Stream not opened! That may be OK.\n");
978dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        goto finish;
988dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
998dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1008dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // Check to see what kind of stream we actually got.
1018dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
1028dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
1038dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    actualDataFormat = AAudioStream_getFormat(aaudioStream);
1048dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    actualDirection = AAudioStream_getDirection(aaudioStream);
1058dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1068dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    printf("          dir = %d, chans = %3d, rate = %6d format = %d\n",
1078dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk           direction, actualChannelCount, actualSampleRate, actualDataFormat);
1088dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1098dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // If we ask for something specific then we should get that.
1108dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    if (channelCount != AAUDIO_UNSPECIFIED) {
1118dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        EXPECT_EQ(channelCount, actualChannelCount);
1128dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
1138dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    if (sampleRate != AAUDIO_UNSPECIFIED) {
1148dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        EXPECT_EQ(sampleRate, actualSampleRate);
1158dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
1168dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    if (format != AAUDIO_FORMAT_UNSPECIFIED) {
1178dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        EXPECT_EQ(format, actualDataFormat);
1188dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
1198dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    EXPECT_EQ(direction, actualDirection);
1208dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1218dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // This is the number of frames that are read in one chunk by a DMA controller
1228dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // or a DSP or a mixer.
1238dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
1248dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
1258dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    printf("          bufferCapacity = %d, remainder = %d\n",
1268dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk           bufferCapacity, bufferCapacity % framesPerBurst);
1278dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1288dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burkfinish:
1298dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStream_close(aaudioStream);
1308dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    AAudioStreamBuilder_delete(aaudioBuilder);
1318dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    printf("          result = %d = %s\n", result, AAudio_convertResultToText(result));
1328dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk}
1338dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1348dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk//void foo() { // for tricking the Android Studio formatter
1358dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil BurkTEST(test_open_params, aaudio_open_all) {
1368dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    aaudio_direction_t directions[] = {AAUDIO_DIRECTION_OUTPUT, AAUDIO_DIRECTION_INPUT};
1379dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk    aaudio_format_t formats[] = {AAUDIO_FORMAT_UNSPECIFIED,
1389dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk                                 AAUDIO_FORMAT_PCM_I16, AAUDIO_FORMAT_PCM_FLOAT};
1398dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    int32_t rates[] = {AAUDIO_UNSPECIFIED, 22050, 32000, 44100, 48000, 88200, 96000, 37913, 59132};
1408dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1418dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // Make printf print immediately so that debug info is not stuck
1428dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    // in a buffer if we hang or crash.
1438dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
1448dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk
1458dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    for (uint dirIndex = 0;dirIndex < arraysize(directions); dirIndex++) {
1468dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        aaudio_direction_t direction = directions[dirIndex];
1478dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        for (int32_t channelCount = 0; channelCount <= 8; channelCount++) {
1488dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk            testOpenOptions(direction, channelCount,
1498dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk                            AAUDIO_UNSPECIFIED, AAUDIO_FORMAT_UNSPECIFIED);
1508dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        }
1518dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        for (uint i = 0; i < arraysize(rates); i++) {
1528dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk            testOpenOptions(direction, AAUDIO_UNSPECIFIED, rates[i], AAUDIO_FORMAT_UNSPECIFIED);
1538dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        }
1548dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        for (uint i = 0; i < arraysize(formats); i++) {
1558dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk            testOpenOptions(direction, AAUDIO_UNSPECIFIED, AAUDIO_UNSPECIFIED, formats[i]);
1568dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk        }
1578dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk    }
1588dd7fedba00b4f21e3428cbb5d5a5014ef9ef49dPhil Burk}
159