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
0 commit comments