CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/android/jni/AndroidAudio.cpp
Views: 1401
1
#include "Common/Log.h"
2
3
#include "android/jni/AndroidAudio.h"
4
#include "android/jni/OpenSLContext.h"
5
6
std::string g_error;
7
std::mutex g_errorMutex;
8
9
AudioContext::AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate)
10
: audioCallback(cb), framesPerBuffer(_FramesPerBuffer), sampleRate(_SampleRate) {
11
if (framesPerBuffer == 0)
12
framesPerBuffer = 256;
13
if (framesPerBuffer < 32)
14
framesPerBuffer = 32;
15
if (framesPerBuffer > 4096)
16
framesPerBuffer = 4096;
17
18
sampleRate = _SampleRate;
19
g_error = "";
20
}
21
22
void AudioContext::SetErrorString(const std::string &error) {
23
std::unique_lock<std::mutex> lock(g_errorMutex);
24
g_error = error;
25
}
26
27
struct AndroidAudioState {
28
AudioContext *ctx = nullptr;
29
AndroidAudioCallback callback = nullptr;
30
// output
31
int frames_per_buffer = 0;
32
int sample_rate = 0;
33
// input
34
int input_enable = 0;
35
int input_sample_rate = 0;
36
};
37
38
AndroidAudioState *AndroidAudio_Init(AndroidAudioCallback callback, int optimalFramesPerBuffer, int optimalSampleRate) {
39
AndroidAudioState *state = new AndroidAudioState();
40
state->callback = callback;
41
state->frames_per_buffer = optimalFramesPerBuffer ? optimalFramesPerBuffer : 256;
42
state->sample_rate = optimalSampleRate ? optimalSampleRate : 44100;
43
return state;
44
}
45
46
bool AndroidAudio_Recording_SetSampleRate(AndroidAudioState *state, int sampleRate) {
47
if (!state) {
48
ERROR_LOG(Log::Audio, "AndroidAudioState not initialized, cannot set recording sample rate");
49
return false;
50
}
51
state->input_sample_rate = sampleRate;
52
INFO_LOG(Log::Audio, "AndroidAudio_Recording_SetSampleRate=%d", sampleRate);
53
return true;
54
}
55
56
bool AndroidAudio_Recording_Start(AndroidAudioState *state) {
57
if (!state) {
58
ERROR_LOG(Log::Audio, "AndroidAudioState not initialized, cannot start recording!");
59
return false;
60
}
61
state->input_enable = 1;
62
if (!state->ctx) {
63
ERROR_LOG(Log::Audio, "OpenSLContext not initialized, cannot start recording!");
64
return false;
65
}
66
state->ctx->AudioRecord_Start(state->input_sample_rate);
67
INFO_LOG(Log::Audio, "AndroidAudio_Recording_Start");
68
return true;
69
}
70
71
bool AndroidAudio_Recording_Stop(AndroidAudioState *state) {
72
if (!state) {
73
ERROR_LOG(Log::Audio, "AndroidAudioState not initialized, cannot stop recording!");
74
return false;
75
}
76
if (!state->ctx) {
77
ERROR_LOG(Log::Audio, "OpenSLContext not initialized, cannot stop recording!");
78
return false;
79
}
80
state->input_enable = 0;
81
state->input_sample_rate = 0;
82
state->ctx->AudioRecord_Stop();
83
INFO_LOG(Log::Audio, "AndroidAudio_Recording_Stop");
84
return true;
85
}
86
87
bool AndroidAudio_Recording_State(AndroidAudioState *state) {
88
if (!state) {
89
return false;
90
}
91
return state->input_enable;
92
}
93
94
bool AndroidAudio_Resume(AndroidAudioState *state) {
95
if (!state) {
96
ERROR_LOG(Log::Audio, "Audio was shutdown, cannot resume!");
97
return false;
98
}
99
if (!state->ctx) {
100
INFO_LOG(Log::Audio, "Calling OpenSLWrap_Init_T...");
101
state->ctx = new OpenSLContext(state->callback, state->frames_per_buffer, state->sample_rate);
102
INFO_LOG(Log::Audio, "Returned from OpenSLWrap_Init_T");
103
bool init_retval = state->ctx->Init();
104
if (!init_retval) {
105
delete state->ctx;
106
state->ctx = nullptr;
107
}
108
if (state->input_enable) {
109
state->ctx->AudioRecord_Start(state->input_sample_rate);
110
}
111
return init_retval;
112
}
113
return false;
114
}
115
116
bool AndroidAudio_Pause(AndroidAudioState *state) {
117
if (!state) {
118
ERROR_LOG(Log::Audio, "Audio was shutdown, cannot pause!");
119
return false;
120
}
121
if (state->ctx) {
122
INFO_LOG(Log::Audio, "Calling OpenSLWrap_Shutdown_T...");
123
delete state->ctx;
124
state->ctx = nullptr;
125
INFO_LOG(Log::Audio, "Returned from OpenSLWrap_Shutdown_T ...");
126
return true;
127
}
128
return false;
129
}
130
131
bool AndroidAudio_Shutdown(AndroidAudioState *state) {
132
if (!state) {
133
ERROR_LOG(Log::Audio, "Audio already shutdown!");
134
return false;
135
}
136
if (state->ctx) {
137
ERROR_LOG(Log::Audio, "Should not shut down when playing! Something is wrong!");
138
return false;
139
}
140
delete state;
141
INFO_LOG(Log::Audio, "OpenSLWrap completely unloaded.");
142
return true;
143
}
144
145
const std::string AndroidAudio_GetErrorString(AndroidAudioState *state) {
146
if (!state) {
147
return "No state";
148
}
149
std::unique_lock<std::mutex> lock(g_errorMutex);
150
return g_error;
151
}
152
153