Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record mic #2

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

dataBinding {
enabled true
}
}

dependencies {
Expand All @@ -28,6 +32,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.fragment:fragment-ktx:1.1.0-alpha09'
implementation 'com.google.android.material:material:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.itochan.aes67mic">

<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand Down
20 changes: 8 additions & 12 deletions app/src/main/java/app/itochan/aes67mic/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package app.itochan.aes67mic

import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity;

import kotlinx.android.synthetic.main.activity_main.*
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import app.itochan.aes67mic.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private val binding by lazy {
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)

fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
setSupportActionBar(binding.toolbar)
}

}
20 changes: 0 additions & 20 deletions app/src/main/java/app/itochan/aes67mic/MainActivityFragment.kt

This file was deleted.

39 changes: 39 additions & 0 deletions app/src/main/java/app/itochan/aes67mic/MicFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package app.itochan.aes67mic

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import app.itochan.aes67mic.databinding.FragmentMicBinding
import com.google.android.material.snackbar.Snackbar

class MicFragment : Fragment() {

private val viewModel: MicViewModel by viewModels()

private lateinit var binding: FragmentMicBinding

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMicBinding.inflate(inflater, container, false)
binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = viewModel
return binding.root
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.recordingStatus.observe(viewLifecycleOwner, Observer {
val text = when (it!!) {
MicViewModel.Status.STARTED -> "Started"
MicViewModel.Status.STOPPED -> "Stopped"
}
Snackbar.make(binding.micButton, text, Snackbar.LENGTH_SHORT).show()
})
}
}
61 changes: 61 additions & 0 deletions app/src/main/java/app/itochan/aes67mic/MicViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package app.itochan.aes67mic

import android.os.Handler
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class MicViewModel : ViewModel() {

private val handler = Handler()
private val statusChecker = object : Runnable {
override fun run() {
showAmplitude()
handler.postDelayed(this, 100)
}
}

private val meter = SoundMeter()

val recordingStatus = MutableLiveData<Status>()
val micButtonText = MutableLiveData<Int>()

val statusText = MutableLiveData<String>()


init {
recordingStatus.value = Status.STOPPED
micButtonText.value = R.string.button_mic_on
}

fun clickMicButton() {
when (recordingStatus.value) {
Status.STOPPED -> startRecord()
Status.STARTED -> stopRecord()
}
}

private fun startRecord() {
recordingStatus.value = Status.STARTED
micButtonText.value = R.string.button_mic_off
statusText.value = "Recording..."

meter.start()
handler.post(statusChecker)
}

private fun stopRecord() {
recordingStatus.value = Status.STOPPED
micButtonText.value = R.string.button_mic_on
statusText.value = "Stopped"

meter.stop()
handler.removeCallbacks(statusChecker)
}

private fun showAmplitude() {
val amplitude = meter.amplitude
statusText.value = "Amplitude: $amplitude"
}

enum class Status { STARTED, STOPPED }
}
44 changes: 44 additions & 0 deletions app/src/main/java/app/itochan/aes67mic/SoundMeter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package app.itochan.aes67mic

import android.media.AudioFormat
import android.media.AudioRecord
import android.media.MediaRecorder

class SoundMeter {

private lateinit var ar: AudioRecord
private var minSize: Int = 0

val amplitude: Double
get() {
val buffer = ShortArray(minSize)
ar.read(buffer, 0, minSize)
var max = 0
for (s in buffer) {
if (Math.abs(s.toInt()) > max) {
max = Math.abs(s.toInt())
}
}
return max.toDouble()
}

fun start() {
minSize = AudioRecord.getMinBufferSize(
8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
)
ar = AudioRecord(
MediaRecorder.AudioSource.MIC,
8000,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
minSize
)
ar.startRecording()
}

fun stop() {
ar.stop()
}
}
37 changes: 16 additions & 21 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<com.google.android.material.appbar.AppBarLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
android:layout_height="match_parent">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

</com.google.android.material.appbar.AppBarLayout>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />

<include layout="@layout/content_main" />
</com.google.android.material.appbar.AppBarLayout>

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
<include layout="@layout/content_main" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
4 changes: 2 additions & 2 deletions app/src/main/res/layout/content_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment"
android:name="app.itochan.aes67mic.MainActivityFragment"
android:name="app.itochan.aes67mic.MicFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_main" />
tools:layout="@layout/fragment_mic" />
10 changes: 0 additions & 10 deletions app/src/main/res/layout/fragment_main.xml

This file was deleted.

41 changes: 41 additions & 0 deletions app/src/main/res/layout/fragment_mic.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".MicFragment"
tools:showIn="@layout/activity_main">

<data>

<variable
name="viewModel"
type="app.itochan.aes67mic.MicViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
android:id="@+id/mic_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.micButtonText}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:onClickListener="@{() -> viewModel.clickMicButton()}" />

<TextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{viewModel.statusText}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mic_button"
tools:text="status" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
1 change: 0 additions & 1 deletion app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
<resources>
<dimen name="fab_margin">16dp</dimen>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
<string name="app_name">aes67mic</string>
<string name="title_activity_main">MainActivity</string>
<string name="action_settings">Settings</string>
<string name="button_mic_on">Mic ON</string>
<string name="button_mic_off">Mic OFF</string>
</resources>