Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Audio record using OpenSL #13575

Merged
merged 3 commits into from
Oct 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Common/System/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@ float System_GetPropertyFloat(SystemProperty prop);
bool System_GetPropertyBool(SystemProperty prop);

std::vector<std::string> __cameraGetDeviceList();
bool audioRecording_Available();
bool audioRecording_State();
17 changes: 11 additions & 6 deletions Core/HLE/sceUsbCam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ static int sceUsbCamReadMicBlocking(u32 bufAddr, u32 size) {
return __MicInputBlocking(size >> 1, config->micParam.frequency, bufAddr);
}

static int sceUsbCamReadMic(u32 bufAddr, u32 size) {
INFO_LOG(HLE, "UNIMPL sceUsbCamReadMic: size: %d", size);
return __MicInputBlocking(size >> 1, config->micParam.frequency, bufAddr);
}

static int sceUsbCamSetupVideo(u32 paramAddr, u32 workareaAddr, int wasize) {
if (Memory::IsValidRange(paramAddr, sizeof(PspUsbCamSetupVideoParam))) {
Memory::ReadStruct(paramAddr, &config->videoParam);
Expand Down Expand Up @@ -185,7 +190,7 @@ static int sceUsbCamReadVideoFrameBlocking(u32 bufAddr, u32 size) {
if (Memory::IsValidRange(bufAddr, size)) {
Memory::Memcpy(bufAddr, videoBuffer, transferSize);
}
return videoBufferLength;
return transferSize;
}

static int sceUsbCamReadVideoFrame(u32 bufAddr, u32 size) {
Expand All @@ -194,7 +199,7 @@ static int sceUsbCamReadVideoFrame(u32 bufAddr, u32 size) {
if (Memory::IsValidRange(bufAddr, size)) {
Memory::Memcpy(bufAddr, videoBuffer, transferSize);
}
nextVideoFrame = videoBufferLength;
nextVideoFrame = transferSize;
return 0;
}

Expand Down Expand Up @@ -243,7 +248,7 @@ const HLEFunction sceUsbCam[] =
{ 0X82A64030, &WrapI_V<sceUsbCamStartMic>, "sceUsbCamStartMic", 'i', "" },
{ 0X5145868A, &WrapI_V<sceUsbCamStopMic>, "sceUsbCamStopMic", 'i', "" },
{ 0X36636925, &WrapI_UU<sceUsbCamReadMicBlocking>, "sceUsbCamReadMicBlocking", 'i', "xx" },
{ 0X3DC0088E, nullptr, "sceUsbCamReadMic", '?', "" },
{ 0X3DC0088E, &WrapI_UU<sceUsbCamReadMic>, "sceUsbCamReadMic", 'i', "xx" },
{ 0XB048A67D, nullptr, "sceUsbCamWaitReadMicEnd", '?', "" },
{ 0XF8847F60, nullptr, "sceUsbCamPollReadMicEnd", '?', "" },
{ 0X5778B452, nullptr, "sceUsbCamGetMicDataLength", '?', "" },
Expand Down Expand Up @@ -301,7 +306,7 @@ void Register_sceUsbCam()
}

std::vector<std::string> Camera::getDeviceList() {
#ifdef HAVE_WIN32_CAMERA
#ifdef HAVE_WIN32_CAMERA
if (winCamera) {
return winCamera->getDeviceList();
}
Expand All @@ -321,7 +326,7 @@ int Camera::startCapture() {
INFO_LOG(HLE, "%s resolution: %dx%d", __FUNCTION__, width, height);

config->mode = Camera::Mode::Video;
#ifdef HAVE_WIN32_CAMERA
#ifdef HAVE_WIN32_CAMERA
if (winCamera) {
if (winCamera->isShutDown()) {
delete winCamera;
Expand All @@ -345,7 +350,7 @@ int Camera::startCapture() {

int Camera::stopCapture() {
INFO_LOG(HLE, "%s", __FUNCTION__);
#ifdef HAVE_WIN32_CAMERA
#ifdef HAVE_WIN32_CAMERA
if (winCamera) {
winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr });
}
Expand Down
4 changes: 3 additions & 1 deletion Core/HLE/sceUsbGps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,16 @@ const HLEFunction sceUsbGps[] =
{0X268F95CA, nullptr, "sceUsbGpsSetInitDataLocation", '?', "" },
{0X31F95CDE, nullptr, "sceUsbGpsGetPowerSaveMode", '?', "" },
{0X54D26AA4, &WrapI_U<sceUsbGpsGetInitDataLocation>, "sceUsbGpsGetInitDataLocation", 'i', "x" },
{0X5881C826, nullptr, "sceUsbGpsGetStaticNavMode", '?', "" },
{0X63D1F89D, nullptr, "sceUsbGpsResetInitialPosition", '?', "" },
{0X69E4AAA8, nullptr, "sceUsbGpsSaveInitData", '?', "" },
{0X6EED4811, &WrapI_V<sceUsbGpsClose>, "sceUsbGpsClose", 'i', "" },
{0X7C16AC3A, &WrapI_U<sceUsbGpsGetState>, "sceUsbGpsGetState", 'i', "x"},
{0X7C16AC3A, &WrapI_U<sceUsbGpsGetState>, "sceUsbGpsGetState", 'i', "x" },
{0X934EC2B2, &WrapI_UU<sceUsbGpsGetData>, "sceUsbGpsGetData", 'i', "xx" },
{0X9D8F99E8, nullptr, "sceUsbGpsSetPowerSaveMode", '?', "" },
{0X9F267D34, &WrapI_V<sceUsbGpsOpen>, "sceUsbGpsOpen", 'i', "" },
{0XA259CD67, nullptr, "sceUsbGpsReset", '?', "" },
{0XA8ED0BC2, nullptr, "sceUsbGpsSetStaticNavMode", '?', "" },
};

void Register_sceUsbGps()
Expand Down
2 changes: 1 addition & 1 deletion Core/HLE/sceUsbGps.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ typedef struct {
float garbage3;
float speed;
float bearing;
} GpsData;
} GpsData;

typedef struct {
unsigned char id;
Expand Down
15 changes: 14 additions & 1 deletion Core/HLE/sceUsbMic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/System/System.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceKernelThread.h"
Expand Down Expand Up @@ -302,6 +303,12 @@ int Microphone::startMic(void *param) {
#ifdef HAVE_WIN32_MICROPHONE
if (winMic)
winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::START, param });
#elif PPSSPP_PLATFORM(ANDROID)
std::vector<u32> *micParam = static_cast<std::vector<u32>*>(param);
int sampleRate = micParam->at(0);
int channels = micParam->at(1);
INFO_LOG(HLE, "microphone_command : sr = %d", sampleRate);
System_SendMessage("microphone_command", ("startRecording:" + std::to_string(sampleRate)).c_str());
#endif
micState = 1;
return 0;
Expand All @@ -311,6 +318,8 @@ int Microphone::stopMic() {
#ifdef HAVE_WIN32_MICROPHONE
if (winMic)
winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr });
#elif PPSSPP_PLATFORM(ANDROID)
System_SendMessage("microphone_command", "stopRecording");
#endif
micState = 0;
return 0;
Expand All @@ -319,6 +328,8 @@ int Microphone::stopMic() {
bool Microphone::isHaveDevice() {
#ifdef HAVE_WIN32_MICROPHONE
return winMic->getDeviceCounts() >= 1;
#elif PPSSPP_PLATFORM(ANDROID)
return audioRecording_Available();
#endif
return false;
}
Expand All @@ -327,6 +338,8 @@ bool Microphone::isMicStarted() {
#ifdef HAVE_WIN32_MICROPHONE
if(winMic)
return winMic->isStarted();
#elif PPSSPP_PLATFORM(ANDROID)
return audioRecording_State();
#endif
return false;
}
Expand Down Expand Up @@ -419,7 +432,7 @@ const HLEFunction sceUsbMic[] =
{0x06128E42, &WrapI_V<sceUsbMicPollInputEnd>, "sceUsbMicPollInputEnd", 'i', "" },
{0x2E6DCDCD, &WrapI_UUU<sceUsbMicInputBlocking>, "sceUsbMicInputBlocking", 'i', "xxx" },
{0x45310F07, &WrapI_U<sceUsbMicInputInitEx>, "sceUsbMicInputInitEx", 'i', "x" },
{0x5F7F368D, &WrapI_V<sceUsbMicInput> , "sceUsbMicInput", 'i', "" },
{0x5F7F368D, &WrapI_V<sceUsbMicInput>, "sceUsbMicInput", 'i', "" },
{0x63400E20, &WrapI_V<sceUsbMicGetInputLength>, "sceUsbMicGetInputLength", 'i', "" },
{0xB8E536EB, &WrapI_III<sceUsbMicInputInit>, "sceUsbMicInputInit", 'i', "iii" },
{0xF899001C, &WrapI_V<sceUsbMicWaitInputEnd>, "sceUsbMicWaitInputEnd", 'i', "" },
Expand Down
1 change: 1 addition & 0 deletions android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.CAMERA" />
<uses-permission-sdk-23 android:name="android.permission.RECORD_AUDIO" />

<supports-screens
android:largeScreens="true"
Expand Down
55 changes: 55 additions & 0 deletions android/jni/AndroidAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ AudioContext::AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _S
struct AndroidAudioState {
AudioContext *ctx = nullptr;
AndroidAudioCallback callback = nullptr;
// output
int frames_per_buffer = 0;
int sample_rate = 0;
// input
int input_enable = 0;
int input_sample_rate = 0;
};

AndroidAudioState *AndroidAudio_Init(AndroidAudioCallback callback, int optimalFramesPerBuffer, int optimalSampleRate) {
Expand All @@ -30,6 +34,54 @@ AndroidAudioState *AndroidAudio_Init(AndroidAudioCallback callback, int optimalF
return state;
}

bool AndroidAudio_Recording_SetSampleRate(AndroidAudioState *state, int sampleRate) {
if (!state) {
ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot set recording sample rate");
return false;
}
state->input_sample_rate = sampleRate;
INFO_LOG(AUDIO, "AndroidAudio_Recording_SetSampleRate=%d", sampleRate);
return true;
}

bool AndroidAudio_Recording_Start(AndroidAudioState *state) {
if (!state) {
ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot start recording!");
return false;
}
state->input_enable = 1;
if (!state->ctx) {
ERROR_LOG(AUDIO, "OpenSLContext not initialized, cannot start recording!");
return false;
}
state->ctx->AudioRecord_Start(state->input_sample_rate);
INFO_LOG(AUDIO, "AndroidAudio_Recording_Start");
return true;
}

bool AndroidAudio_Recording_Stop(AndroidAudioState *state) {
if (!state) {
ERROR_LOG(AUDIO, "AndroidAudioState not initialized, cannot stop recording!");
return false;
}
if (!state->ctx) {
ERROR_LOG(AUDIO, "OpenSLContext not initialized, cannot stop recording!");
return false;
}
state->input_enable = 0;
state->input_sample_rate = 0;
state->ctx->AudioRecord_Stop();
INFO_LOG(AUDIO, "AndroidAudio_Recording_Stop");
return true;
}

bool AndroidAudio_Recording_State(AndroidAudioState *state) {
if (!state) {
return false;
}
return state->input_enable;
}

bool AndroidAudio_Resume(AndroidAudioState *state) {
if (!state) {
ERROR_LOG(AUDIO, "Audio was shutdown, cannot resume!");
Expand All @@ -44,6 +96,9 @@ bool AndroidAudio_Resume(AndroidAudioState *state) {
delete state->ctx;
state->ctx = nullptr;
}
if (state->input_enable) {
state->ctx->AudioRecord_Start(state->input_sample_rate);
}
return init_retval;
}
return false;
Expand Down
6 changes: 6 additions & 0 deletions android/jni/AndroidAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class AudioContext {
public:
AudioContext(AndroidAudioCallback cb, int _FramesPerBuffer, int _SampleRate);
virtual bool Init() { return false; }
virtual int AudioRecord_Start(int sampleRate) { return false; };
virtual int AudioRecord_Stop() { return false; };
virtual ~AudioContext() {}

protected:
Expand All @@ -21,6 +23,10 @@ struct AndroidAudioState;

// It's okay for optimalFramesPerBuffer and optimalSampleRate to be 0. Defaults will be used.
AndroidAudioState *AndroidAudio_Init(AndroidAudioCallback cb, int optimalFramesPerBuffer, int optimalSampleRate);
bool AndroidAudio_Recording_SetSampleRate(AndroidAudioState *state, int sampleRate);
bool AndroidAudio_Recording_Start(AndroidAudioState *state);
bool AndroidAudio_Recording_Stop(AndroidAudioState *state);
bool AndroidAudio_Recording_State(AndroidAudioState *state);
bool AndroidAudio_Pause(AndroidAudioState *state);
bool AndroidAudio_Resume(AndroidAudioState *state);
bool AndroidAudio_Shutdown(AndroidAudioState *state);
Loading