-
Notifications
You must be signed in to change notification settings - Fork 2
/
sys_aaudio.c
141 lines (119 loc) · 4.07 KB
/
sys_aaudio.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
Faun Android backend using AAudio (API level 26)
*/
#include <aaudio/AAudio.h>
#include <android/log.h>
static const char* sysaudio_open(const char* appName)
{
(void) appName;
return NULL;
}
static void sysaudio_close()
{
}
static const char* sysaudio_allocVoice(FaunVoice* voice, int updateHz,
const char* appName)
{
AAudioStream* stream;
AAudioStreamBuilder* bld;
aaudio_result_t res;
int32_t abufferCap;
int32_t abufferSize;
int32_t framesPerBurst;
int32_t mixLen;
int mixRate = voice->mix.rate;
int fmt;
int chan = faun_channelCount(voice->mix.chanLayout);
voice->backend = NULL;
switch (voice->mix.format) {
case FAUN_S16:
fmt = AAUDIO_FORMAT_PCM_I16;
voice->frameBytes = chan * sizeof(int16_t);
break;
case FAUN_F32:
fmt = AAUDIO_FORMAT_PCM_FLOAT;
voice->frameBytes = chan * sizeof(float);
break;
default:
return "Invalid Faun sample format for AAudio";
}
res = AAudio_createStreamBuilder(&bld);
if (res != AAUDIO_OK)
return "Cannot create AAudio stream builder";
// Use the default device & direction (output stream).
AAudioStreamBuilder_setSharingMode(bld, AAUDIO_SHARING_MODE_SHARED);
AAudioStreamBuilder_setSampleRate(bld, mixRate);
AAudioStreamBuilder_setChannelCount(bld, chan);
AAudioStreamBuilder_setFormat(bld, fmt);
AAudioStreamBuilder_setBufferCapacityInFrames(bld, (mixRate/updateHz) * 2);
/*
AAudioStreamBuilder_setPerformanceMode(bld,
AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
*/
res = AAudioStreamBuilder_openStream(bld, &stream);
AAudioStreamBuilder_delete(bld);
if (res != AAUDIO_OK)
return "Cannot open AAudio stream";
framesPerBurst = AAudioStream_getFramesPerBurst(stream);
// Set voice->mix.used to one or two bursts.
mixLen = framesPerBurst;
if ((mixRate / framesPerBurst) > 66)
mixLen += framesPerBurst;
faun_reserve(&voice->mix, mixLen);
voice->mix.used = mixLen;
voice->updateHz = mixRate / mixLen;
AAudioStream_setBufferSizeInFrames(stream, mixLen * 2);
abufferSize = AAudioStream_getBufferSizeInFrames(stream);
abufferCap = AAudioStream_getBufferCapacityInFrames(stream);
#if 1
__android_log_print(ANDROID_LOG_INFO, "faun",
"mix: %d hz: %d\n(capacity: %d size: %d burst: %d)\n",
voice->mix.used,
voice->updateHz,
abufferCap, abufferSize, framesPerBurst);
#endif
res = AAudioStream_requestStart(stream);
if (res != AAUDIO_OK) {
AAudioStream_close(stream);
return "Cannot start AAudio stream";
}
voice->backend = stream;
return NULL;
}
static void sysaudio_freeVoice(FaunVoice *voice)
{
AAudioStream_close((AAudioStream*) voice->backend);
voice->backend = NULL;
}
static const char* sysaudio_write(FaunVoice* voice, const void* data,
uint32_t len)
{
AAudioStream* stream = (AAudioStream*) voice->backend;
aaudio_result_t res;
int32_t numFrames = len / voice->frameBytes;
/*
AAudio docs say:
Audio latency is high for blocking write() because the Android O DP2
release doesn't use a FAST track. Use a callback to get lower latency.
*/
res = AAudioStream_write(stream, data, numFrames, 25000000);
if (res < 0)
return AAudio_convertResultToText(res);
#if 1
if (res != numFrames)
__android_log_print(ANDROID_LOG_WARN, "faun",
"underrun: %d\n",
AAudioStream_getXRunCount(stream));
#endif
return NULL;
}
static int sysaudio_startVoice(FaunVoice *voice)
{
AAudioStream* stream = (AAudioStream*) voice->backend;
return (AAudioStream_requestStart(stream) == AAUDIO_OK);
}
static int sysaudio_stopVoice(FaunVoice *voice)
{
AAudioStream* stream = (AAudioStream*) voice->backend;
return (AAudioStream_requestPause(stream) == AAUDIO_OK);
}