mirror of
https://github.com/SimpleMobileTools/Simple-Voice-Recorder.git
synced 2025-06-05 21:59:31 +02:00
adding a recording audio visualizer
This commit is contained in:
@ -40,4 +40,5 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.simplemobiletools:commons:5.24.4'
|
implementation 'com.simplemobiletools:commons:5.24.4'
|
||||||
implementation 'org.greenrobot:eventbus:3.2.0'
|
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||||
|
implementation 'com.github.Armen101:AudioRecordView:1.0.2'
|
||||||
}
|
}
|
||||||
|
@ -44,10 +44,13 @@ class MainActivity : SimpleActivity() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
val adjustedPrimaryColor = getAdjustedPrimaryColor()
|
||||||
toggle_recording_button.apply {
|
toggle_recording_button.apply {
|
||||||
setImageDrawable(getToggleButtonIcon())
|
setImageDrawable(getToggleButtonIcon())
|
||||||
background.applyColorFilter(getAdjustedPrimaryColor())
|
background.applyColorFilter(adjustedPrimaryColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visualizer.chunkColor = adjustedPrimaryColor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
@ -134,6 +137,15 @@ class MainActivity : SimpleActivity() {
|
|||||||
fun gotStatusEvent(event: Events.RecordingStatus) {
|
fun gotStatusEvent(event: Events.RecordingStatus) {
|
||||||
isRecording = event.isRecording
|
isRecording = event.isRecording
|
||||||
toggle_recording_button.setImageDrawable(getToggleButtonIcon())
|
toggle_recording_button.setImageDrawable(getToggleButtonIcon())
|
||||||
|
if (isRecording) {
|
||||||
|
visualizer.recreate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun gotAmplitudeEvent(event: Events.RecordingAmplitude) {
|
||||||
|
val amplitude = event.amplitude
|
||||||
|
visualizer.update(amplitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getToggleButtonIcon(): Drawable {
|
private fun getToggleButtonIcon(): Drawable {
|
||||||
|
@ -3,4 +3,5 @@ package com.simplemobiletools.voicerecorder.models
|
|||||||
class Events {
|
class Events {
|
||||||
class RecordingDuration internal constructor(val duration: Int)
|
class RecordingDuration internal constructor(val duration: Int)
|
||||||
class RecordingStatus internal constructor(val isRecording: Boolean)
|
class RecordingStatus internal constructor(val isRecording: Boolean)
|
||||||
|
class RecordingAmplitude internal constructor(val amplitude: Int)
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,13 @@ import java.io.IOException
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class RecorderService : Service() {
|
class RecorderService : Service() {
|
||||||
|
private val AMPLITUDE_UPDATE_MS = 100L
|
||||||
|
|
||||||
private var currFilePath = ""
|
private var currFilePath = ""
|
||||||
private var duration = 0
|
private var duration = 0
|
||||||
private var isRecording = false
|
private var isRecording = false
|
||||||
private var timer = Timer()
|
private var durationTimer = Timer()
|
||||||
|
private var amplitudeTimer = Timer()
|
||||||
private var recorder: MediaRecorder? = null
|
private var recorder: MediaRecorder? = null
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? = null
|
override fun onBind(intent: Intent?): IBinder? = null
|
||||||
@ -50,8 +53,6 @@ class RecorderService : Service() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
stopRecording()
|
stopRecording()
|
||||||
recorder?.release()
|
|
||||||
recorder = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// mp4 output format with aac encoding should produce good enough mp3 files according to https://stackoverflow.com/a/33054794/1967672
|
// mp4 output format with aac encoding should produce good enough mp3 files according to https://stackoverflow.com/a/33054794/1967672
|
||||||
@ -81,8 +82,11 @@ class RecorderService : Service() {
|
|||||||
broadcastRecorderInfo()
|
broadcastRecorderInfo()
|
||||||
startForeground(RECORDER_RUNNING_NOTIF_ID, showNotification())
|
startForeground(RECORDER_RUNNING_NOTIF_ID, showNotification())
|
||||||
|
|
||||||
timer = Timer()
|
durationTimer = Timer()
|
||||||
timer.scheduleAtFixedRate(getTimerTask(), 1000, 1000)
|
durationTimer.scheduleAtFixedRate(getDurationUpdateTask(), 1000, 1000)
|
||||||
|
|
||||||
|
amplitudeTimer = Timer()
|
||||||
|
amplitudeTimer.scheduleAtFixedRate(getAmplitudeUpdateTask(), 0, AMPLITUDE_UPDATE_MS)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
showErrorToast(e)
|
showErrorToast(e)
|
||||||
stopRecording()
|
stopRecording()
|
||||||
@ -91,7 +95,8 @@ class RecorderService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun stopRecording() {
|
private fun stopRecording() {
|
||||||
timer.cancel()
|
durationTimer.cancel()
|
||||||
|
amplitudeTimer.cancel()
|
||||||
isRecording = false
|
isRecording = false
|
||||||
|
|
||||||
recorder?.apply {
|
recorder?.apply {
|
||||||
@ -151,13 +156,21 @@ class RecorderService : Service() {
|
|||||||
toast(msg, Toast.LENGTH_LONG)
|
toast(msg, Toast.LENGTH_LONG)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTimerTask() = object : TimerTask() {
|
private fun getDurationUpdateTask() = object : TimerTask() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
duration++
|
duration++
|
||||||
broadcastDuration()
|
broadcastDuration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getAmplitudeUpdateTask() = object : TimerTask() {
|
||||||
|
override fun run() {
|
||||||
|
if (recorder != null) {
|
||||||
|
EventBus.getDefault().post(Events.RecordingAmplitude(recorder!!.maxAmplitude))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.O)
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
private fun showNotification(): Notification {
|
private fun showNotification(): Notification {
|
||||||
val channelId = "simple_recorder"
|
val channelId = "simple_recorder"
|
||||||
|
@ -1,10 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/recorder_holder"
|
android:id="@+id/recorder_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.visualizer.amplitude.AudioRecordView
|
||||||
|
android:id="@+id/visualizer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_above="@+id/recording_duration"
|
||||||
|
android:layout_marginTop="@dimen/activity_margin"
|
||||||
|
android:layout_marginEnd="@dimen/activity_margin"
|
||||||
|
android:layout_marginBottom="@dimen/activity_margin"
|
||||||
|
app:chunkAlignTo="center"
|
||||||
|
app:chunkMaxHeight="200dp"
|
||||||
|
app:chunkMinHeight="2dp"
|
||||||
|
app:chunkRoundedCorners="true"
|
||||||
|
app:chunkSoftTransition="true"
|
||||||
|
app:chunkSpace="1dp"
|
||||||
|
app:chunkWidth="3dp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/recording_duration"
|
android:id="@+id/recording_duration"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
Reference in New Issue
Block a user