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 
AudioContext(AndroidAudioCallback cb,int _FramesPerBuffer,int _SampleRate)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 
SetErrorString(const std::string & error)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 
AndroidAudio_Init(AndroidAudioCallback callback,int optimalFramesPerBuffer,int optimalSampleRate)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 
AndroidAudio_Recording_SetSampleRate(AndroidAudioState * state,int sampleRate)46 bool AndroidAudio_Recording_SetSampleRate(AndroidAudioState *state, int sampleRate) {
47 	if (!state) {
48 		ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot set recording sample rate");
49 		return false;
50 	}
51 	state->input_sample_rate = sampleRate;
52 	INFO_LOG(AUDIO, "AndroidAudio_Recording_SetSampleRate=%d", sampleRate);
53 	return true;
54 }
55 
AndroidAudio_Recording_Start(AndroidAudioState * state)56 bool AndroidAudio_Recording_Start(AndroidAudioState *state) {
57 	if (!state) {
58 		ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot start recording!");
59 		return false;
60 	}
61 	state->input_enable = 1;
62 	if (!state->ctx) {
63 		ERROR_LOG(AUDIO, "OpenSLContext not initialized, cannot start recording!");
64 		return false;
65 	}
66 	state->ctx->AudioRecord_Start(state->input_sample_rate);
67 	INFO_LOG(AUDIO, "AndroidAudio_Recording_Start");
68 	return true;
69 }
70 
AndroidAudio_Recording_Stop(AndroidAudioState * state)71 bool AndroidAudio_Recording_Stop(AndroidAudioState *state) {
72 	if (!state) {
73 		ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot stop recording!");
74 		return false;
75 	}
76 	if (!state->ctx) {
77 		ERROR_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(AUDIO, "AndroidAudio_Recording_Stop");
84 	return true;
85 }
86 
AndroidAudio_Recording_State(AndroidAudioState * state)87 bool AndroidAudio_Recording_State(AndroidAudioState *state) {
88 	if (!state) {
89 		return false;
90 	}
91 	return state->input_enable;
92 }
93 
AndroidAudio_Resume(AndroidAudioState * state)94 bool AndroidAudio_Resume(AndroidAudioState *state) {
95 	if (!state) {
96 		ERROR_LOG(AUDIO, "Audio was shutdown, cannot resume!");
97 		return false;
98 	}
99 	if (!state->ctx) {
100 		INFO_LOG(AUDIO, "Calling OpenSLWrap_Init_T...");
101 		state->ctx = new OpenSLContext(state->callback, state->frames_per_buffer, state->sample_rate);
102 		INFO_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 
AndroidAudio_Pause(AndroidAudioState * state)116 bool AndroidAudio_Pause(AndroidAudioState *state) {
117 	if (!state) {
118 		ERROR_LOG(AUDIO, "Audio was shutdown, cannot pause!");
119 		return false;
120 	}
121 	if (state->ctx) {
122 		INFO_LOG(AUDIO, "Calling OpenSLWrap_Shutdown_T...");
123 		delete state->ctx;
124 		state->ctx = nullptr;
125 		INFO_LOG(AUDIO, "Returned from OpenSLWrap_Shutdown_T ...");
126 		return true;
127 	}
128 	return false;
129 }
130 
AndroidAudio_Shutdown(AndroidAudioState * state)131 bool AndroidAudio_Shutdown(AndroidAudioState *state) {
132 	if (!state) {
133 		ERROR_LOG(AUDIO, "Audio already shutdown!");
134 		return false;
135 	}
136 	if (state->ctx) {
137 		ERROR_LOG(AUDIO, "Should not shut down when playing! Something is wrong!");
138 		return false;
139 	}
140 	delete state;
141 	INFO_LOG(AUDIO, "OpenSLWrap completely unloaded.");
142 	return true;
143 }
144 
AndroidAudio_GetErrorString(AndroidAudioState * state)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