mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-23 16:37:30 +00:00
124 lines
4.4 KiB
C++
124 lines
4.4 KiB
C++
|
#include "MicrophoneReader.h"
|
||
|
#include "SampleRateUtil.h"
|
||
|
|
||
|
#include <jni.h>
|
||
|
|
||
|
#include <android/log.h>
|
||
|
|
||
|
#define TAG "MicrophoneReader"
|
||
|
|
||
|
#ifndef SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION
|
||
|
#define SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION ((SLuint32) 0x00000004)
|
||
|
#endif
|
||
|
|
||
|
MicrophoneReader::MicrophoneReader(int androidSdkVersion, AudioCodec &audioCodec, RtpAudioSender &rtpAudioSender, Clock &clock) :
|
||
|
androidSdkVersion(androidSdkVersion), muteEnabled(0),
|
||
|
audioCodec(audioCodec), rtpAudioSender(rtpAudioSender), clock(clock),
|
||
|
recorderObject(NULL), recorderRecord(NULL), recorderBufferQueue(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
MicrophoneReader::~MicrophoneReader() {
|
||
|
}
|
||
|
|
||
|
void MicrophoneReader::recorderCallback(SLAndroidSimpleBufferQueueItf bufferQueue, void *context) {
|
||
|
MicrophoneReader* microphoneReader = static_cast<MicrophoneReader*>(context);
|
||
|
microphoneReader->recorderCallback(bufferQueue);
|
||
|
}
|
||
|
|
||
|
void MicrophoneReader::recorderCallback(SLAndroidSimpleBufferQueueItf bufferQueue)
|
||
|
{
|
||
|
if (muteEnabled) {
|
||
|
memset(inputBuffer, 0, FRAME_SIZE * 2 * sizeof(short));
|
||
|
}
|
||
|
|
||
|
int encodedAudioLen = audioCodec.encode(inputBuffer, encodedAudio, sizeof(encodedAudio));
|
||
|
encodedAudioLen += audioCodec.encode(inputBuffer + FRAME_SIZE, encodedAudio + encodedAudioLen, sizeof(encodedAudio) - encodedAudioLen);
|
||
|
|
||
|
rtpAudioSender.send(clock.tick(2), encodedAudio, encodedAudioLen);
|
||
|
|
||
|
(*bufferQueue)->Enqueue(bufferQueue, inputBuffer, FRAME_SIZE * 2 * sizeof(short));
|
||
|
}
|
||
|
|
||
|
void MicrophoneReader::setMute(int muteEnabled) {
|
||
|
this->muteEnabled = muteEnabled;
|
||
|
}
|
||
|
|
||
|
int MicrophoneReader::start(SLEngineItf *engineEnginePtr) {
|
||
|
SLEngineItf engineEngine = *engineEnginePtr;
|
||
|
|
||
|
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
|
||
|
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8,
|
||
|
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
|
||
|
SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
|
||
|
|
||
|
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
|
||
|
|
||
|
SLDataSource audioSrc = {&loc_dev, NULL};
|
||
|
SLDataSink audioSnk = {&loc_bq, &format_pcm};
|
||
|
|
||
|
const SLInterfaceID id[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
|
||
|
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||
|
|
||
|
if ((*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc,
|
||
|
&audioSnk, 2, id, req) != SL_RESULT_SUCCESS)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDCONFIGURATION, &androidConfig) == SL_RESULT_SUCCESS) {
|
||
|
SLint32 recordingPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
|
||
|
|
||
|
if (androidSdkVersion >= 14) {
|
||
|
__android_log_print(ANDROID_LOG_WARN, TAG, "Using voice communication Microphone preset...");
|
||
|
recordingPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
|
||
|
}
|
||
|
|
||
|
(*androidConfig)->SetConfiguration(androidConfig, SL_ANDROID_KEY_RECORDING_PRESET,
|
||
|
&recordingPreset, sizeof(SLint32));
|
||
|
}
|
||
|
|
||
|
if ((*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, &MicrophoneReader::recorderCallback, this) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderBufferQueue)->Enqueue(recorderBufferQueue, inputBuffer, FRAME_SIZE * 2 * sizeof(short)) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ((*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING) != SL_RESULT_SUCCESS) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void MicrophoneReader::stop() {
|
||
|
if (recorderRecord != NULL) {
|
||
|
(*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
|
||
|
}
|
||
|
|
||
|
if (recorderBufferQueue != NULL) {
|
||
|
(*recorderBufferQueue)->Clear(recorderBufferQueue);
|
||
|
}
|
||
|
|
||
|
if (recorderObject != NULL) {
|
||
|
(*recorderObject)->Destroy(recorderObject);
|
||
|
|
||
|
recorderRecord = NULL;
|
||
|
recorderObject = NULL;
|
||
|
recorderBufferQueue = NULL;
|
||
|
}
|
||
|
}
|