Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.
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 Installer/package.txt
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ component Extensions
rfolder macosx:packaged_extensions/com.livecode.widget.iconpicker
into [[ToolsFolder]]/Extensions place
rfolder macosx:packaged_extensions/com.livecode.library.androidbgaudio
into [[ToolsFolder]]/Extensions place
rfolder macosx:packaged_extensions/com.livecode.library.androidaudiorecorder
into [[ToolsFolder]]/Extensions place
rfolder macosx:packaged_extensions/com.livecode.library.iconsvg
into [[ToolsFolder]]/Extensions place
Expand Down
1 change: 1 addition & 0 deletions extensions/extensions.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'modules/scriptitems/scriptitems.lcb',

'libraries/androidbgaudio/androidbgaudio.lcb',
'libraries/androidaudiorecorder/androidaudiorecorder.lcb',
'libraries/canvas/canvas.lcb',
'libraries/iconsvg/iconsvg.lcb',
'libraries/json/json.lcb',
Expand Down
311 changes: 311 additions & 0 deletions extensions/libraries/androidaudiorecorder/androidaudiorecorder.lcb
Original file line number Diff line number Diff line change
@@ -0,0 +1,311 @@
/**
This library provides Android audio recording functionality, via the
android.media.MediaRecorder class.

Description:
Use this library to record audio on Android.

>*Note:* This library requires RECORD_AUDIO, WRITE_EXTERNAL_STORAGE and
> CAPTURE_AUDIO_OUTPUT permissions. These will be automatically added to
> the application manifest when an application including this library is
> built.
*/

library com.livecode.library.androidaudiorecorder

metadata version is "1.0.0"
metadata author is "LiveCode"
metadata title is "Android Audio Recorder"

-- We need permissions to record audio and write to the external
-- storage directory.
metadata android.permissions is "RECORD_AUDIO,CAPTURE_AUDIO_OUTPUT"

use com.livecode.foreign
use com.livecode.java

__safe foreign handler _JNI_MediaRecorderConstructor() returns JObject \
binds to "java:android.media.MediaRecorder>new()"
__safe foreign handler _JNI_MediaRecorderSetRecordInput(in pRecorder as JObject, in pSource as JInt) returns nothing \
binds to "java:android.media.MediaRecorder>setAudioSource(I)V"
__safe foreign handler _JNI_MediaRecorderSetRecordFormat(in pRecorder as JObject, in pFormat as JInt) returns nothing \
binds to "java:android.media.MediaRecorder>setOutputFormat(I)V"
__safe foreign handler _JNI_MediaRecorderSetRecordEncoder(in pRecorder as JObject, in pEncoder as JInt) returns nothing \
binds to "java:android.media.MediaRecorder>setAudioEncoder(I)V"
__safe foreign handler _JNI_MediaRecorderSetRecordOutputFile(in pRecorder as JObject, in pFile as JString) returns nothing \
binds to "java:android.media.MediaRecorder>setOutputFile(Ljava/lang/String;)V"
__safe foreign handler _JNI_MediaRecorderPrepare(in pRecorder as JObject) returns nothing \
binds to "java:android.media.MediaRecorder>prepare()V"
__safe foreign handler _JNI_MediaRecorderStart(in pRecorder as JObject) returns nothing \
binds to "java:android.media.MediaRecorder>start()V"
__safe foreign handler _JNI_MediaRecorderStop(in pRecorder as JObject) returns nothing \
binds to "java:android.media.MediaRecorder>stop()V"
__safe foreign handler _JNI_MediaRecorderReset(in pRecorder as JObject) returns nothing \
binds to "java:android.media.MediaRecorder>reset()V"
__safe foreign handler _JNI_MediaRecorderGetMaxAmplitude(in pRecorder as JObject) returns JInt \
binds to "java:android.media.MediaRecorder>getMaxAmplitude()I"

-- This will store an instance of a MediaRecorder
private variable mRecorder as optional JObject

constant kRecordInputs is { \
"Default" : 0, \
"Mic" : 1, \
"VoiceUplink" : 2, \
"VoiceDownlink" : 3, \
"VoiceCall" : 4, \
"Camcorder" : 5, \
"VoiceRecognition" : 6, \
"VoiceCommunication" : 7, \
"RemoteSubmix" : 8, \
"Unprocessed" : 9 \
}
constant kRecordCompressionTypes is { \
"Default" : 0, \
"AMR NB" : 1, \
"AMR WB" : 2, \
"AAC" : 3, \
"HE AAC" : 4, \
"AAC ELD" : 5, \
"Vorbis" : 6 \
}
constant kRecordFormats is { \
"ThreeGPP" : 1, \
"MPEG-4" : 2, \
"AMR WB" : 4, \
"AAC ADTS" : 6, \
"WebM" : 9 \
}

private variable mRecordInput as optional String
private variable mRecordFormat as optional String
private variable mRecordCompressionType as optional String

private handler IsAndroid() returns Boolean
return the operating system is "android"
end handler

handler GetOptionalProperty(in pVar as optional String, in pDefault as String) returns String
if pVar is not nothing then
return pVar
end if
return pDefault
end handler

handler SetRecorderProperties() returns nothing
if not IsAndroid() then
throw "Not supported on this platform"
end if

if mRecorder is nothing then
return
end if

variable tRecordInput as String
put GetOptionalProperty(mRecordInput, "Mic") into tRecordInput
variable tRecordFormat as String
put GetOptionalProperty(mRecordFormat, "ThreeGPP") into tRecordFormat
variable tRecordCompressionType as String
put GetOptionalProperty(mRecordCompressionType, "AMR NB") into tRecordCompressionType

_JNI_MediaRecorderSetRecordInput(mRecorder, kRecordInputs[tRecordInput])
_JNI_MediaRecorderSetRecordFormat(mRecorder, kRecordFormats[tRecordFormat])
_JNI_MediaRecorderSetRecordEncoder(mRecorder, kRecordCompressionTypes[tRecordCompressionType])
end handler

handler CreateRecorder() returns nothing
if mRecorder is nothing then
put _JNI_MediaRecorderConstructor() into mRecorder
end if

SetRecorderProperties()
end handler

/**
Summary: Start recording an audio file, using the given filename

Example:
local tFilePath
put specialFolderPath("external documents") & slash & "recording.mp4" \
into tFilePath
androidRecorderStartRecording tFilePath

Parameters:
pFileName: The absolute filename of the output file

Description:
Use the <androidRecorderStartRecording> handler to start recording audio
on Android using the input source, compression type and output format
selected using the <androidRecorderSetRecordInput>,
<androidRecorderSetRecordCompressionType>, and <androidRecorderSetRecordFormat>
handlers. The default input source, compression and output format are
built-in microphone, AMR-NB and 3gpp respectively.

References:
androidRecorderSetRecordInput (handler),
androidRecorderSetRecordCompressionType (handler),
androidRecorderSetRecordFormat (handler)
*/
public handler androidRecorderStartRecording(in pFileName as String) returns nothing
if not IsAndroid() then
throw "Not supported on this platform"
end if

CreateRecorder()

if mRecorder is nothing then
throw "unable to create recorder"
end if

_JNI_MediaRecorderSetRecordOutputFile(mRecorder, StringToJString(pFileName))
_JNI_MediaRecorderPrepare(mRecorder)
_JNI_MediaRecorderStart(mRecorder)
end handler

/**
Summary: Stop recording

Example:
on mouseUp
try
androidRecorderStopRecording
catch tError
answer tError
end try
end mouseUp

Description:
Use the <androidRecorderStopRecording> handler to stop the current
recording. If no recording is currently happening, this handler will
throw an error.
*/
public handler androidRecorderStopRecording()
-- Don't do anything if there is no recorder object
if mRecorder is nothing then
throw "recording has not been started!"
return
end if

_JNI_MediaRecorderStop(mRecorder)
_JNI_MediaRecorderReset(mRecorder)
end handler

/**
Summary: Returns the max amplitude of the recording since last sampled

Example:
-- Poll amplitude every 30 millisecs, and output values
command LogAmplitude
put androidRecorderGetMaxAmplitude()
send "LogAmplitude" to me in 30 millisecs
end UpdateAmplitudeAndTimer

Description:
Use the <androidRecorderGetMaxAmplitude> handler to retrieve the maximum
amplitude value reached during recording from the selected input source
since the amplitude was last retrieved.

<androidRecorderGetMaxAmplitude> returns 0 if no recording is currently
happening.
*/

--
public handler androidRecorderGetMaxAmplitude() returns Integer
if mRecorder is nothing then
return 0
end if
return _JNI_MediaRecorderGetMaxAmplitude(mRecorder)
end handler

/**
Summary: Set the record input source

Example:
androidRecorderSetRecordInput "mic"

Parameters:
pInputSource (enum): The record input source
- "Default": The device's default record input source
- "Mic": Microphone audio source
- "VoiceUplink": Voice call uplink (Tx) audio source
- "VoiceDownlink": Voice call uplink (Tx) audio source.
- "VoiceCall": Voice call uplink + downlink audio source
- "Camcorder": Microphone audio source tuned for video recording, with the same orientation as the camera if available
- "VoiceRecognition": Microphone audio source tuned for voice recognition
- "VoiceCommunication": Microphone audio source tuned for voice recognition
- "RemoteSubmix": Audio source for a submix of audio streams to be presented remotely
- "Unprocessed": Microphone audio source tuned for unprocessed (raw) sound if available, behaves like Default otherwise

Description:
Use the <androidRecorderSetRecordInput> handler to control the source
and tuning of the record input.
*/
public handler androidRecorderSetRecordInput(in pInputSource as String)
if pInputSource is not among the keys of kRecordInputs then
throw "unrecognised source"
return
end if

put pInputSource into mRecordInput
SetRecorderProperties()
end handler

/**
Summary: Set the record compression type

Example:
androidRecorderSetRecordCompressionType "AMR NB"

Parameters:
pCompressionType (enum): The record compression type
- "Default": The default compression type
- "AMR NB": AMR Narrowband
- "AMR WB": AMR Wideband
- "AAC": AAC Low Complexity (AAC-LC)
- "HE AAC": High Efficiency AAC (HE-AAC)
- "AAC ELD": Enhanced Low Delay AAC (AAC-ELD)
- "Vorbis" : Ogg Vorbis

Description:
Use the <androidRecorderSetRecordCompressionType> handler to control the
audio encoding used by the audio recorder.
*/
public handler androidRecorderSetRecordCompressionType(in pCompressionType as String)
if pCompressionType is not among the keys of kRecordCompressionTypes then
throw "unrecognised compression type"
return
end if

put pCompressionType into mRecordCompressionType
SetRecorderProperties()
end handler

/**
Summary: Set the record output format

Example:
androidRecorderSetRecordFormat "ThreeGPP"

Parameters:
pRecordFormat (enum): The record output format
"ThreeGPP":
"MPEG-4":
"AMR WB":
"AAC ADTS":
"WebM":

Description:
Use the <androidRecorderSetRecordFormat> handler to set the format of
the output file.
*/

public handler androidRecorderSetRecordFormat(in pRecordFormat as String)
if pRecordFormat is not among the keys of kRecordFormats then
throw "unrecognised source"
return
end if

put pRecordFormat into mRecordFormat
SetRecorderProperties()
end handler
end library
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Android Audio Recorder
An android audio recorder has been added. As well as starting and
stopping recording, it allows the selection of various input
sources, encoding types and output formats. The library places
the following handlers in the message path:
- `androidRecorderStartRecording pFileName`: Start recording an audio file, using the given filename
- `androidRecorderStopRecording`: Stop recording
- `androidRecorderGetMaxAmplitude`: Returns the max amplitude of the recording since last sampled
- `androidRecorderSetRecordCompressionType pType`: Set the record compression type
- `androidRecorderSetRecordFormat pFormat`: Set the record output format
- `androidRecorderSetRecordInput pSource`: Set the record input source