Skip to content

Commit b246916

Browse files
authored
Merge pull request livecode#5941 from livecodeali/feature-android_audio_recorder
[[ AndroidAudioRecorder ]] Add android audio recorder library
2 parents e22f462 + be9d708 commit b246916

5 files changed

Lines changed: 326 additions & 0 deletions

File tree

Installer/package.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ component Extensions
423423
rfolder macosx:packaged_extensions/com.livecode.widget.iconpicker
424424
into [[ToolsFolder]]/Extensions place
425425
rfolder macosx:packaged_extensions/com.livecode.library.androidbgaudio
426+
into [[ToolsFolder]]/Extensions place
427+
rfolder macosx:packaged_extensions/com.livecode.library.androidaudiorecorder
426428
into [[ToolsFolder]]/Extensions place
427429
rfolder macosx:packaged_extensions/com.livecode.library.iconsvg
428430
into [[ToolsFolder]]/Extensions place

extensions/extensions.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'modules/scriptitems/scriptitems.lcb',
2323

2424
'libraries/androidbgaudio/androidbgaudio.lcb',
25+
'libraries/androidaudiorecorder/androidaudiorecorder.lcb',
2526
'libraries/canvas/canvas.lcb',
2627
'libraries/iconsvg/iconsvg.lcb',
2728
'libraries/json/json.lcb',
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/**
2+
This library provides Android audio recording functionality, via the
3+
android.media.MediaRecorder class.
4+
5+
Description:
6+
Use this library to record audio on Android.
7+
8+
>*Note:* This library requires RECORD_AUDIO, WRITE_EXTERNAL_STORAGE and
9+
> CAPTURE_AUDIO_OUTPUT permissions. These will be automatically added to
10+
> the application manifest when an application including this library is
11+
> built.
12+
*/
13+
14+
library com.livecode.library.androidaudiorecorder
15+
16+
metadata version is "1.0.0"
17+
metadata author is "LiveCode"
18+
metadata title is "Android Audio Recorder"
19+
20+
-- We need permissions to record audio and write to the external
21+
-- storage directory.
22+
metadata android.permissions is "RECORD_AUDIO,CAPTURE_AUDIO_OUTPUT"
23+
24+
use com.livecode.foreign
25+
use com.livecode.java
26+
27+
__safe foreign handler _JNI_MediaRecorderConstructor() returns JObject \
28+
binds to "java:android.media.MediaRecorder>new()"
29+
__safe foreign handler _JNI_MediaRecorderSetRecordInput(in pRecorder as JObject, in pSource as JInt) returns nothing \
30+
binds to "java:android.media.MediaRecorder>setAudioSource(I)V"
31+
__safe foreign handler _JNI_MediaRecorderSetRecordFormat(in pRecorder as JObject, in pFormat as JInt) returns nothing \
32+
binds to "java:android.media.MediaRecorder>setOutputFormat(I)V"
33+
__safe foreign handler _JNI_MediaRecorderSetRecordEncoder(in pRecorder as JObject, in pEncoder as JInt) returns nothing \
34+
binds to "java:android.media.MediaRecorder>setAudioEncoder(I)V"
35+
__safe foreign handler _JNI_MediaRecorderSetRecordOutputFile(in pRecorder as JObject, in pFile as JString) returns nothing \
36+
binds to "java:android.media.MediaRecorder>setOutputFile(Ljava/lang/String;)V"
37+
__safe foreign handler _JNI_MediaRecorderPrepare(in pRecorder as JObject) returns nothing \
38+
binds to "java:android.media.MediaRecorder>prepare()V"
39+
__safe foreign handler _JNI_MediaRecorderStart(in pRecorder as JObject) returns nothing \
40+
binds to "java:android.media.MediaRecorder>start()V"
41+
__safe foreign handler _JNI_MediaRecorderStop(in pRecorder as JObject) returns nothing \
42+
binds to "java:android.media.MediaRecorder>stop()V"
43+
__safe foreign handler _JNI_MediaRecorderReset(in pRecorder as JObject) returns nothing \
44+
binds to "java:android.media.MediaRecorder>reset()V"
45+
__safe foreign handler _JNI_MediaRecorderGetMaxAmplitude(in pRecorder as JObject) returns JInt \
46+
binds to "java:android.media.MediaRecorder>getMaxAmplitude()I"
47+
48+
-- This will store an instance of a MediaRecorder
49+
private variable mRecorder as optional JObject
50+
51+
constant kRecordInputs is { \
52+
"Default" : 0, \
53+
"Mic" : 1, \
54+
"VoiceUplink" : 2, \
55+
"VoiceDownlink" : 3, \
56+
"VoiceCall" : 4, \
57+
"Camcorder" : 5, \
58+
"VoiceRecognition" : 6, \
59+
"VoiceCommunication" : 7, \
60+
"RemoteSubmix" : 8, \
61+
"Unprocessed" : 9 \
62+
}
63+
constant kRecordCompressionTypes is { \
64+
"Default" : 0, \
65+
"AMR NB" : 1, \
66+
"AMR WB" : 2, \
67+
"AAC" : 3, \
68+
"HE AAC" : 4, \
69+
"AAC ELD" : 5, \
70+
"Vorbis" : 6 \
71+
}
72+
constant kRecordFormats is { \
73+
"ThreeGPP" : 1, \
74+
"MPEG-4" : 2, \
75+
"AMR WB" : 4, \
76+
"AAC ADTS" : 6, \
77+
"WebM" : 9 \
78+
}
79+
80+
private variable mRecordInput as optional String
81+
private variable mRecordFormat as optional String
82+
private variable mRecordCompressionType as optional String
83+
84+
private handler IsAndroid() returns Boolean
85+
return the operating system is "android"
86+
end handler
87+
88+
handler GetOptionalProperty(in pVar as optional String, in pDefault as String) returns String
89+
if pVar is not nothing then
90+
return pVar
91+
end if
92+
return pDefault
93+
end handler
94+
95+
handler SetRecorderProperties() returns nothing
96+
if not IsAndroid() then
97+
throw "Not supported on this platform"
98+
end if
99+
100+
if mRecorder is nothing then
101+
return
102+
end if
103+
104+
variable tRecordInput as String
105+
put GetOptionalProperty(mRecordInput, "Mic") into tRecordInput
106+
variable tRecordFormat as String
107+
put GetOptionalProperty(mRecordFormat, "ThreeGPP") into tRecordFormat
108+
variable tRecordCompressionType as String
109+
put GetOptionalProperty(mRecordCompressionType, "AMR NB") into tRecordCompressionType
110+
111+
_JNI_MediaRecorderSetRecordInput(mRecorder, kRecordInputs[tRecordInput])
112+
_JNI_MediaRecorderSetRecordFormat(mRecorder, kRecordFormats[tRecordFormat])
113+
_JNI_MediaRecorderSetRecordEncoder(mRecorder, kRecordCompressionTypes[tRecordCompressionType])
114+
end handler
115+
116+
handler CreateRecorder() returns nothing
117+
if mRecorder is nothing then
118+
put _JNI_MediaRecorderConstructor() into mRecorder
119+
end if
120+
121+
SetRecorderProperties()
122+
end handler
123+
124+
/**
125+
Summary: Start recording an audio file, using the given filename
126+
127+
Example:
128+
local tFilePath
129+
put specialFolderPath("external documents") & slash & "recording.mp4" \
130+
into tFilePath
131+
androidRecorderStartRecording tFilePath
132+
133+
Parameters:
134+
pFileName: The absolute filename of the output file
135+
136+
Description:
137+
Use the <androidRecorderStartRecording> handler to start recording audio
138+
on Android using the input source, compression type and output format
139+
selected using the <androidRecorderSetRecordInput>,
140+
<androidRecorderSetRecordCompressionType>, and <androidRecorderSetRecordFormat>
141+
handlers. The default input source, compression and output format are
142+
built-in microphone, AMR-NB and 3gpp respectively.
143+
144+
References:
145+
androidRecorderSetRecordInput (handler),
146+
androidRecorderSetRecordCompressionType (handler),
147+
androidRecorderSetRecordFormat (handler)
148+
*/
149+
public handler androidRecorderStartRecording(in pFileName as String) returns nothing
150+
if not IsAndroid() then
151+
throw "Not supported on this platform"
152+
end if
153+
154+
CreateRecorder()
155+
156+
if mRecorder is nothing then
157+
throw "unable to create recorder"
158+
end if
159+
160+
_JNI_MediaRecorderSetRecordOutputFile(mRecorder, StringToJString(pFileName))
161+
_JNI_MediaRecorderPrepare(mRecorder)
162+
_JNI_MediaRecorderStart(mRecorder)
163+
end handler
164+
165+
/**
166+
Summary: Stop recording
167+
168+
Example:
169+
on mouseUp
170+
try
171+
androidRecorderStopRecording
172+
catch tError
173+
answer tError
174+
end try
175+
end mouseUp
176+
177+
Description:
178+
Use the <androidRecorderStopRecording> handler to stop the current
179+
recording. If no recording is currently happening, this handler will
180+
throw an error.
181+
*/
182+
public handler androidRecorderStopRecording()
183+
-- Don't do anything if there is no recorder object
184+
if mRecorder is nothing then
185+
throw "recording has not been started!"
186+
return
187+
end if
188+
189+
_JNI_MediaRecorderStop(mRecorder)
190+
_JNI_MediaRecorderReset(mRecorder)
191+
end handler
192+
193+
/**
194+
Summary: Returns the max amplitude of the recording since last sampled
195+
196+
Example:
197+
-- Poll amplitude every 30 millisecs, and output values
198+
command LogAmplitude
199+
put androidRecorderGetMaxAmplitude()
200+
send "LogAmplitude" to me in 30 millisecs
201+
end UpdateAmplitudeAndTimer
202+
203+
Description:
204+
Use the <androidRecorderGetMaxAmplitude> handler to retrieve the maximum
205+
amplitude value reached during recording from the selected input source
206+
since the amplitude was last retrieved.
207+
208+
<androidRecorderGetMaxAmplitude> returns 0 if no recording is currently
209+
happening.
210+
*/
211+
212+
--
213+
public handler androidRecorderGetMaxAmplitude() returns Integer
214+
if mRecorder is nothing then
215+
return 0
216+
end if
217+
return _JNI_MediaRecorderGetMaxAmplitude(mRecorder)
218+
end handler
219+
220+
/**
221+
Summary: Set the record input source
222+
223+
Example:
224+
androidRecorderSetRecordInput "mic"
225+
226+
Parameters:
227+
pInputSource (enum): The record input source
228+
- "Default": The device's default record input source
229+
- "Mic": Microphone audio source
230+
- "VoiceUplink": Voice call uplink (Tx) audio source
231+
- "VoiceDownlink": Voice call uplink (Tx) audio source.
232+
- "VoiceCall": Voice call uplink + downlink audio source
233+
- "Camcorder": Microphone audio source tuned for video recording, with the same orientation as the camera if available
234+
- "VoiceRecognition": Microphone audio source tuned for voice recognition
235+
- "VoiceCommunication": Microphone audio source tuned for voice recognition
236+
- "RemoteSubmix": Audio source for a submix of audio streams to be presented remotely
237+
- "Unprocessed": Microphone audio source tuned for unprocessed (raw) sound if available, behaves like Default otherwise
238+
239+
Description:
240+
Use the <androidRecorderSetRecordInput> handler to control the source
241+
and tuning of the record input.
242+
*/
243+
public handler androidRecorderSetRecordInput(in pInputSource as String)
244+
if pInputSource is not among the keys of kRecordInputs then
245+
throw "unrecognised source"
246+
return
247+
end if
248+
249+
put pInputSource into mRecordInput
250+
SetRecorderProperties()
251+
end handler
252+
253+
/**
254+
Summary: Set the record compression type
255+
256+
Example:
257+
androidRecorderSetRecordCompressionType "AMR NB"
258+
259+
Parameters:
260+
pCompressionType (enum): The record compression type
261+
- "Default": The default compression type
262+
- "AMR NB": AMR Narrowband
263+
- "AMR WB": AMR Wideband
264+
- "AAC": AAC Low Complexity (AAC-LC)
265+
- "HE AAC": High Efficiency AAC (HE-AAC)
266+
- "AAC ELD": Enhanced Low Delay AAC (AAC-ELD)
267+
- "Vorbis" : Ogg Vorbis
268+
269+
Description:
270+
Use the <androidRecorderSetRecordCompressionType> handler to control the
271+
audio encoding used by the audio recorder.
272+
*/
273+
public handler androidRecorderSetRecordCompressionType(in pCompressionType as String)
274+
if pCompressionType is not among the keys of kRecordCompressionTypes then
275+
throw "unrecognised compression type"
276+
return
277+
end if
278+
279+
put pCompressionType into mRecordCompressionType
280+
SetRecorderProperties()
281+
end handler
282+
283+
/**
284+
Summary: Set the record output format
285+
286+
Example:
287+
androidRecorderSetRecordFormat "ThreeGPP"
288+
289+
Parameters:
290+
pRecordFormat (enum): The record output format
291+
"ThreeGPP":
292+
"MPEG-4":
293+
"AMR WB":
294+
"AAC ADTS":
295+
"WebM":
296+
297+
Description:
298+
Use the <androidRecorderSetRecordFormat> handler to set the format of
299+
the output file.
300+
*/
301+
302+
public handler androidRecorderSetRecordFormat(in pRecordFormat as String)
303+
if pRecordFormat is not among the keys of kRecordFormats then
304+
throw "unrecognised source"
305+
return
306+
end if
307+
308+
put pRecordFormat into mRecordFormat
309+
SetRecorderProperties()
310+
end handler
311+
end library
5.27 KB
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Android Audio Recorder
2+
An android audio recorder has been added. As well as starting and
3+
stopping recording, it allows the selection of various input
4+
sources, encoding types and output formats. The library places
5+
the following handlers in the message path:
6+
- `androidRecorderStartRecording pFileName`: Start recording an audio file, using the given filename
7+
- `androidRecorderStopRecording`: Stop recording
8+
- `androidRecorderGetMaxAmplitude`: Returns the max amplitude of the recording since last sampled
9+
- `androidRecorderSetRecordCompressionType pType`: Set the record compression type
10+
- `androidRecorderSetRecordFormat pFormat`: Set the record output format
11+
- `androidRecorderSetRecordInput pSource`: Set the record input source
12+

0 commit comments

Comments
 (0)