-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathRNLiveAudioStreamModule.java
More file actions
127 lines (102 loc) · 3.92 KB
/
Copy pathRNLiveAudioStreamModule.java
File metadata and controls
127 lines (102 loc) · 3.92 KB
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
package com.imxiqi.rnliveaudiostream;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.util.Base64;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import java.lang.Math;
public class RNLiveAudioStreamModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
private int sampleRateInHz;
private int channelConfig;
private int audioFormat;
private int audioSource;
private AudioRecord recorder;
private int bufferSize;
private boolean isRecording;
public RNLiveAudioStreamModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "RNLiveAudioStream";
}
@ReactMethod
public void init(ReadableMap options) {
sampleRateInHz = 44100;
if (options.hasKey("sampleRate")) {
sampleRateInHz = options.getInt("sampleRate");
}
channelConfig = AudioFormat.CHANNEL_IN_MONO;
if (options.hasKey("channels")) {
if (options.getInt("channels") == 2) {
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
}
}
audioFormat = AudioFormat.ENCODING_PCM_16BIT;
if (options.hasKey("bitsPerSample")) {
if (options.getInt("bitsPerSample") == 8) {
audioFormat = AudioFormat.ENCODING_PCM_8BIT;
}
}
audioSource = AudioSource.VOICE_RECOGNITION;
if (options.hasKey("audioSource")) {
audioSource = options.getInt("audioSource");
}
isRecording = false;
eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
if (options.hasKey("bufferSize")) {
bufferSize = Math.max(bufferSize, options.getInt("bufferSize"));
}
int recordingBufferSize = bufferSize * 3;
recorder = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, recordingBufferSize);
}
@ReactMethod
public void start() {
isRecording = true;
recorder.startRecording();
Thread recordingThread = new Thread(new Runnable() {
public void run() {
try {
int bytesRead;
int count = 0;
String base64Data;
byte[] buffer = new byte[bufferSize];
while (isRecording) {
bytesRead = recorder.read(buffer, 0, buffer.length);
// skip first 2 buffers to eliminate "click sound"
if (bytesRead > 0 && ++count > 2) {
base64Data = Base64.encodeToString(buffer, Base64.NO_WRAP);
eventEmitter.emit("data", base64Data);
}
}
recorder.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
});
recordingThread.start();
}
@ReactMethod
public void stop(Promise promise) {
isRecording = false;
}
@ReactMethod
public void addListener(String eventName) {
// Keep: Required for RN built in Event Emitter Calls.
}
@ReactMethod
public void removeListeners(Integer count) {
// Keep: Required for RN built in Event Emitter Calls.
}
}