1e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk/*
2e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Copyright (C) 2017 The Android Open Source Project
3e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
4e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * you may not use this file except in compliance with the License.
6e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * You may obtain a copy of the License at
7e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
8e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk *
10e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * Unless required by applicable law or agreed to in writing, software
11e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * See the License for the specific language governing permissions and
14e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk * limitations under the License.
15e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk */
16e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
17e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Play sine waves using an AAudio callback.
18e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
19e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <assert.h>
20e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <unistd.h>
21e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <stdlib.h>
22e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <sched.h>
23e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <stdio.h>
24e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <math.h>
25e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <time.h>
26e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <aaudio/AAudio.h>
27629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#include "AAudioExampleUtils.h"
28629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent#include "AAudioSimplePlayer.h"
29e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
30e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk#define NUM_SECONDS              5
31e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
32e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Application data that gets passed to the callback.
33e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define MAX_FRAME_COUNT_RECORDS    256
34e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkint main(int argc, char **argv)
36e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk{
37e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    (void)argc; // unused
38629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    AAudioSimplePlayer player;
39e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    SineThreadedData_t myData;
40e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    aaudio_result_t result;
41e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
42e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Make printf print immediately so that debug info is not stuck
43e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // in a buffer if we hang or crash.
44e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
45e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk    printf("%s - Play a sine sweep using an AAudio callback\n", argv[0]);
46e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
47e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    myData.schedulerChecked = false;
48e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
49629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent    result = player.open(2, 44100, AAUDIO_FORMAT_PCM_FLOAT,
50629afae6135e6dc1e88ab4080f984fb30b3cdd7cEric Laurent                         SimplePlayerDataCallbackProc, SimplePlayerErrorCallbackProc, &myData);
51e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
52e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        fprintf(stderr, "ERROR -  player.open() returned %d\n", result);
53e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        goto error;
54e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
55e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond());
5620523edbf2f597c53b90e76694331c807e559515Phil Burk    printf("player.getChannelCount() = %d\n", player.getChannelCount());
57e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    myData.sineOsc1.setup(440.0, 48000);
58e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
59e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    myData.sineOsc2.setup(660.0, 48000);
60e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
61e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
62e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#if 0
63e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    result = player.prime(); // FIXME crashes AudioTrack.cpp
64e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
65e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        fprintf(stderr, "ERROR - player.prime() returned %d\n", result);
66e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        goto error;
67e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
68e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#endif
69e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
70e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    result = player.start();
71e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
72e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        fprintf(stderr, "ERROR - player.start() returned %d\n", result);
73e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        goto error;
74e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
75e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
76e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    printf("Sleep for %d seconds while audio plays in a callback thread.\n", NUM_SECONDS);
77e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    for (int second = 0; second < NUM_SECONDS; second++)
78e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    {
79e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        const struct timespec request = { .tv_sec = 1, .tv_nsec = 0 };
80e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        (void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
81e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
82e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        aaudio_stream_state_t state;
83e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        result = AAudioStream_waitForStateChange(player.getStream(),
84e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk                                                 AAUDIO_STREAM_STATE_CLOSED,
85e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk                                                 &state,
86e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk                                                 0);
87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        if (result != AAUDIO_OK) {
88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            fprintf(stderr, "ERROR - AAudioStream_waitForStateChange() returned %d\n", result);
89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            goto error;
90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        }
91e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        if (state != AAUDIO_STREAM_STATE_STARTING && state != AAUDIO_STREAM_STATE_STARTED) {
92e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            printf("Stream state is %d %s!\n", state, AAudio_convertStreamStateToText(state));
93e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
94e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        }
95e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk        printf("framesWritten = %d\n", (int) AAudioStream_getFramesWritten(player.getStream()));
96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    printf("Woke up now.\n");
98e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
9971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    printf("call stop()\n");
100e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    result = player.stop();
101e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
102e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        goto error;
103e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
10471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    printf("call close()\n");
105e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    result = player.close();
106e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (result != AAUDIO_OK) {
107e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        goto error;
108e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
109e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
110e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (myData.schedulerChecked) {
111e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        printf("scheduler = 0x%08x, SCHED_FIFO = 0x%08X\n",
112e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk               myData.scheduler,
113e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk               SCHED_FIFO);
114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
115e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
116e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    printf("SUCCESS\n");
117e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return EXIT_SUCCESS;
118e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkerror:
119e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    player.close();
120e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    printf("exiting - AAudio result = %d = %s\n", result, AAudio_convertResultToText(result));
121e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return EXIT_FAILURE;
122e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
123e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
124