mirror of
https://github.com/xdsopl/robot36.git
synced 2026-02-13 01:34:14 +01:00
added menu with audio and night mode settings
This commit is contained in:
parent
e1cebdab3c
commit
8325abf6a2
|
|
@ -193,11 +193,12 @@ public class Decoder {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean process(float[] recordBuffer) {
|
||||
boolean syncPulseDetected = demodulator.process(recordBuffer);
|
||||
public boolean process(float[] recordBuffer, int channelSelect) {
|
||||
boolean syncPulseDetected = demodulator.process(recordBuffer, channelSelect);
|
||||
int syncPulseIndex = curSample + demodulator.syncPulseOffset;
|
||||
for (float v : recordBuffer) {
|
||||
scanLineBuffer[curSample++] = v;
|
||||
int channels = channelSelect > 0 ? 2 : 1;
|
||||
for (int j = 0; j < recordBuffer.length / channels; ++j) {
|
||||
scanLineBuffer[curSample++] = recordBuffer[j];
|
||||
if (curSample >= scanLineBuffer.length) {
|
||||
int shift = scanLineReserveSamples;
|
||||
syncPulseIndex -= shift;
|
||||
|
|
|
|||
|
|
@ -77,10 +77,27 @@ public class Demodulator {
|
|||
baseBand = new Complex();
|
||||
}
|
||||
|
||||
public boolean process(float[] buffer) {
|
||||
public boolean process(float[] buffer, int channelSelect) {
|
||||
boolean syncPulseDetected = false;
|
||||
for (int i = 0; i < buffer.length; ++i) {
|
||||
baseBand = baseBandLowPass.push(baseBand.set(buffer[i]).mul(baseBandOscillator.rotate()));
|
||||
int channels = channelSelect > 0 ? 2 : 1;
|
||||
for (int i = 0; i < buffer.length / channels; ++i) {
|
||||
switch (channelSelect) {
|
||||
case 1:
|
||||
baseBand.set(buffer[2 * i]);
|
||||
break;
|
||||
case 2:
|
||||
baseBand.set(buffer[2 * i + 1]);
|
||||
break;
|
||||
case 3:
|
||||
baseBand.set(buffer[2 * i] + buffer[2 * i + 1]);
|
||||
break;
|
||||
case 4:
|
||||
baseBand.set(buffer[2 * i], buffer[2 * i + 1]);
|
||||
break;
|
||||
default:
|
||||
baseBand.set(buffer[i]);
|
||||
}
|
||||
baseBand = baseBandLowPass.push(baseBand.mul(baseBandOscillator.rotate()));
|
||||
float frequencyValue = frequencyModulation.demod(baseBand);
|
||||
float syncPulseValue = syncPulseFilter.avg(frequencyValue);
|
||||
float syncPulseDelayedValue = syncPulseValueDelay.push(syncPulseValue);
|
||||
|
|
|
|||
|
|
@ -7,18 +7,22 @@ Copyright 2024 Ahmet Inan <xdsopl@gmail.com>
|
|||
package xdsopl.robot36;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioRecord;
|
||||
import android.media.MediaRecorder;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
|
|
@ -35,11 +39,18 @@ public class MainActivity extends AppCompatActivity {
|
|||
private ImageView scopeView;
|
||||
private float[] recordBuffer;
|
||||
private AudioRecord audioRecord;
|
||||
private TextView status;
|
||||
private Decoder decoder;
|
||||
private Menu menu;
|
||||
private int recordRate;
|
||||
private int recordChannel;
|
||||
private int audioSource;
|
||||
|
||||
private void setStatus(int id) {
|
||||
status.setText(id);
|
||||
setTitle(id);
|
||||
}
|
||||
|
||||
private void setStatus(String str) {
|
||||
setTitle(str);
|
||||
}
|
||||
|
||||
private final AudioRecord.OnRecordPositionUpdateListener recordListener = new AudioRecord.OnRecordPositionUpdateListener() {
|
||||
|
|
@ -50,31 +61,46 @@ public class MainActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public void onPeriodicNotification(AudioRecord audioRecord) {
|
||||
audioRecord.read(recordBuffer, 0, recordBuffer.length, AudioRecord.READ_BLOCKING);
|
||||
if (decoder.process(recordBuffer)) {
|
||||
if (decoder.process(recordBuffer, recordChannel)) {
|
||||
scopeBitmap.setPixels(scopeBuffer.pixels, scopeBuffer.width * decoder.curLine, scopeBuffer.width, 0, 0, scopeBuffer.width, scopeBuffer.height / 2);
|
||||
scopeView.invalidate();
|
||||
status.setText(decoder.lastMode.getName());
|
||||
setStatus(decoder.lastMode.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void initAudioRecord() {
|
||||
int audioSource = MediaRecorder.AudioSource.UNPROCESSED;
|
||||
boolean rateChanged = true;
|
||||
if (audioRecord != null) {
|
||||
rateChanged = audioRecord.getSampleRate() != recordRate;
|
||||
boolean channelChanged = audioRecord.getChannelCount() != (recordChannel == 0 ? 1 : 2);
|
||||
boolean sourceChanged = audioRecord.getAudioSource() != audioSource;
|
||||
if (!rateChanged && !channelChanged && !sourceChanged)
|
||||
return;
|
||||
stopListening();
|
||||
audioRecord.release();
|
||||
audioRecord = null;
|
||||
}
|
||||
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
|
||||
int audioFormat = AudioFormat.ENCODING_PCM_FLOAT;
|
||||
int sampleRate = 8000;
|
||||
int sampleSize = 4;
|
||||
int channelCount = 1;
|
||||
if (recordChannel != 0) {
|
||||
channelCount = 2;
|
||||
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
|
||||
}
|
||||
int sampleSize = 4;
|
||||
int frameSize = sampleSize * channelCount;
|
||||
int audioFormat = AudioFormat.ENCODING_PCM_FLOAT;
|
||||
int readsPerSecond = 50;
|
||||
double bufferSeconds = 0.5;
|
||||
int bufferSize = (int) (bufferSeconds * sampleRate * sampleSize);
|
||||
recordBuffer = new float[(sampleRate * channelCount) / readsPerSecond];
|
||||
int bufferSize = Integer.highestOneBit(recordRate) * frameSize;
|
||||
int frameCount = recordRate / readsPerSecond;
|
||||
recordBuffer = new float[frameCount * channelCount];
|
||||
try {
|
||||
audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize);
|
||||
audioRecord = new AudioRecord(audioSource, recordRate, channelConfig, audioFormat, bufferSize);
|
||||
if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
|
||||
audioRecord.setRecordPositionUpdateListener(recordListener);
|
||||
audioRecord.setPositionNotificationPeriod(recordBuffer.length);
|
||||
decoder = new Decoder(scopeBuffer, sampleRate);
|
||||
audioRecord.setPositionNotificationPeriod(frameCount);
|
||||
if (rateChanged)
|
||||
decoder = new Decoder(scopeBuffer, recordRate);
|
||||
startListening();
|
||||
} else {
|
||||
setStatus(R.string.audio_init_failed);
|
||||
|
|
@ -103,6 +129,90 @@ public class MainActivity extends AppCompatActivity {
|
|||
audioRecord.stop();
|
||||
}
|
||||
|
||||
private void setRecordRate(int newSampleRate) {
|
||||
if (recordRate == newSampleRate)
|
||||
return;
|
||||
recordRate = newSampleRate;
|
||||
updateRecordRateMenu();
|
||||
initAudioRecord();
|
||||
}
|
||||
|
||||
private void setRecordChannel(int newChannelSelect) {
|
||||
if (recordChannel == newChannelSelect)
|
||||
return;
|
||||
recordChannel = newChannelSelect;
|
||||
updateRecordChannelMenu();
|
||||
initAudioRecord();
|
||||
}
|
||||
|
||||
private void setAudioSource(int newAudioSource) {
|
||||
if (audioSource == newAudioSource)
|
||||
return;
|
||||
audioSource = newAudioSource;
|
||||
updateAudioSourceMenu();
|
||||
initAudioRecord();
|
||||
}
|
||||
|
||||
private void updateRecordRateMenu() {
|
||||
switch (recordRate) {
|
||||
case 8000:
|
||||
menu.findItem(R.id.action_set_record_rate_8000).setChecked(true);
|
||||
break;
|
||||
case 16000:
|
||||
menu.findItem(R.id.action_set_record_rate_16000).setChecked(true);
|
||||
break;
|
||||
case 32000:
|
||||
menu.findItem(R.id.action_set_record_rate_32000).setChecked(true);
|
||||
break;
|
||||
case 44100:
|
||||
menu.findItem(R.id.action_set_record_rate_44100).setChecked(true);
|
||||
break;
|
||||
case 48000:
|
||||
menu.findItem(R.id.action_set_record_rate_48000).setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRecordChannelMenu() {
|
||||
switch (recordChannel) {
|
||||
case 0:
|
||||
menu.findItem(R.id.action_set_record_channel_default).setChecked(true);
|
||||
break;
|
||||
case 1:
|
||||
menu.findItem(R.id.action_set_record_channel_first).setChecked(true);
|
||||
break;
|
||||
case 2:
|
||||
menu.findItem(R.id.action_set_record_channel_second).setChecked(true);
|
||||
break;
|
||||
case 3:
|
||||
menu.findItem(R.id.action_set_record_channel_summation).setChecked(true);
|
||||
break;
|
||||
case 4:
|
||||
menu.findItem(R.id.action_set_record_channel_analytic).setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAudioSourceMenu() {
|
||||
switch (audioSource) {
|
||||
case MediaRecorder.AudioSource.DEFAULT:
|
||||
menu.findItem(R.id.action_set_source_default).setChecked(true);
|
||||
break;
|
||||
case MediaRecorder.AudioSource.MIC:
|
||||
menu.findItem(R.id.action_set_source_microphone).setChecked(true);
|
||||
break;
|
||||
case MediaRecorder.AudioSource.CAMCORDER:
|
||||
menu.findItem(R.id.action_set_source_camcorder).setChecked(true);
|
||||
break;
|
||||
case MediaRecorder.AudioSource.VOICE_RECOGNITION:
|
||||
menu.findItem(R.id.action_set_source_voice_recognition).setChecked(true);
|
||||
break;
|
||||
case MediaRecorder.AudioSource.UNPROCESSED:
|
||||
menu.findItem(R.id.action_set_source_unprocessed).setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private final int permissionID = 1;
|
||||
|
||||
@Override
|
||||
|
|
@ -116,8 +226,42 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
protected void onSaveInstanceState(@NonNull Bundle state) {
|
||||
state.putInt("nightMode", AppCompatDelegate.getDefaultNightMode());
|
||||
state.putInt("recordRate", recordRate);
|
||||
state.putInt("recordChannel", recordChannel);
|
||||
state.putInt("audioSource", audioSource);
|
||||
super.onSaveInstanceState(state);
|
||||
}
|
||||
|
||||
private void storeSettings() {
|
||||
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor edit = pref.edit();
|
||||
edit.putInt("nightMode", AppCompatDelegate.getDefaultNightMode());
|
||||
edit.putInt("recordRate", recordRate);
|
||||
edit.putInt("recordChannel", recordChannel);
|
||||
edit.putInt("audioSource", audioSource);
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle state) {
|
||||
final int defaultSampleRate = 8000;
|
||||
final int defaultChannelSelect = 0;
|
||||
final int defaultAudioSource = MediaRecorder.AudioSource.DEFAULT;
|
||||
if (state == null) {
|
||||
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
|
||||
AppCompatDelegate.setDefaultNightMode(pref.getInt("nightMode", AppCompatDelegate.getDefaultNightMode()));
|
||||
recordRate = pref.getInt("recordRate", defaultSampleRate);
|
||||
recordChannel = pref.getInt("recordChannel", defaultChannelSelect);
|
||||
audioSource = pref.getInt("audioSource", defaultAudioSource);
|
||||
} else {
|
||||
AppCompatDelegate.setDefaultNightMode(state.getInt("nightMode", AppCompatDelegate.getDefaultNightMode()));
|
||||
recordRate = state.getInt("recordRate", defaultSampleRate);
|
||||
recordChannel = state.getInt("recordChannel", defaultChannelSelect);
|
||||
audioSource = state.getInt("audioSource", defaultAudioSource);
|
||||
}
|
||||
super.onCreate(state);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
|
|
@ -125,7 +269,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
status = findViewById(R.id.status);
|
||||
scopeView = findViewById(R.id.scope);
|
||||
int scopeWidth = 640;
|
||||
int scopeHeight = 1280;
|
||||
|
|
@ -143,6 +286,90 @@ public class MainActivity extends AppCompatActivity {
|
|||
ActivityCompat.requestPermissions(this, permissions.toArray(new String[0]), permissionID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
this.menu = menu;
|
||||
updateRecordRateMenu();
|
||||
updateRecordChannelMenu();
|
||||
updateAudioSourceMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.action_set_record_rate_8000) {
|
||||
setRecordRate(8000);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_rate_16000) {
|
||||
setRecordRate(16000);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_rate_32000) {
|
||||
setRecordRate(32000);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_rate_44100) {
|
||||
setRecordRate(44100);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_rate_48000) {
|
||||
setRecordRate(48000);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_channel_default) {
|
||||
setRecordChannel(0);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_channel_first) {
|
||||
setRecordChannel(1);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_channel_second) {
|
||||
setRecordChannel(2);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_channel_summation) {
|
||||
setRecordChannel(3);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_record_channel_analytic) {
|
||||
setRecordChannel(4);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_source_default) {
|
||||
setAudioSource(MediaRecorder.AudioSource.DEFAULT);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_source_microphone) {
|
||||
setAudioSource(MediaRecorder.AudioSource.MIC);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_source_camcorder) {
|
||||
setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_source_voice_recognition) {
|
||||
setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_set_source_unprocessed) {
|
||||
setAudioSource(MediaRecorder.AudioSource.UNPROCESSED);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_enable_night_mode) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
return true;
|
||||
}
|
||||
if (id == R.id.action_disable_night_mode) {
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
startListening();
|
||||
|
|
@ -152,6 +379,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onPause() {
|
||||
stopListening();
|
||||
storeSettings();
|
||||
super.onPause();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,5 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
82
app/src/main/res/menu/menu_main.xml
Normal file
82
app/src/main/res/menu/menu_main.xml
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="xdsopl.robot36.MainActivity">
|
||||
<item android:title="@string/audio_settings">
|
||||
<menu>
|
||||
<item android:title="@string/sample_rate">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/action_set_record_rate_8000"
|
||||
android:title="@string/rate_8000" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_rate_16000"
|
||||
android:title="@string/rate_16000" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_rate_32000"
|
||||
android:title="@string/rate_32000" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_rate_44100"
|
||||
android:title="@string/rate_44100" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_rate_48000"
|
||||
android:title="@string/rate_48000" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:title="@string/channel_select">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/action_set_record_channel_default"
|
||||
android:title="@string/channel_default" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_channel_first"
|
||||
android:title="@string/channel_first" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_channel_second"
|
||||
android:title="@string/channel_second" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_channel_summation"
|
||||
android:title="@string/channel_summation" />
|
||||
<item
|
||||
android:id="@+id/action_set_record_channel_analytic"
|
||||
android:title="@string/channel_analytic" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:title="@string/audio_source">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/action_set_source_default"
|
||||
android:title="@string/source_default" />
|
||||
<item
|
||||
android:id="@+id/action_set_source_microphone"
|
||||
android:title="@string/source_microphone" />
|
||||
<item
|
||||
android:id="@+id/action_set_source_camcorder"
|
||||
android:title="@string/source_camcorder" />
|
||||
<item
|
||||
android:id="@+id/action_set_source_voice_recognition"
|
||||
android:title="@string/source_voice_recognition" />
|
||||
<item
|
||||
android:id="@+id/action_set_source_unprocessed"
|
||||
android:title="@string/source_unprocessed" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:title="@string/night_mode">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/action_enable_night_mode"
|
||||
android:title="@string/enable" />
|
||||
<item
|
||||
android:id="@+id/action_disable_night_mode"
|
||||
android:title="@string/disable" />
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.Robot36" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<style name="Base.Theme.Robot36" parent="Theme.Material3.DayNight">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,31 @@
|
|||
<resources>
|
||||
<string name="app_name">Robot36</string>
|
||||
<string name="listening">listening</string>
|
||||
<string name="audio_init_failed">audio init failed</string>
|
||||
<string name="audio_setup_failed">audio setup failed</string>
|
||||
<string name="audio_permission_denied">audio permission denied</string>
|
||||
<string name="audio_recording_error">audio recording error</string>
|
||||
<string name="scope_description">visualization of audio signal</string>
|
||||
<string name="listening">Listening</string>
|
||||
<string name="audio_settings">Audio Settings</string>
|
||||
<string name="sample_rate">Sample Rate</string>
|
||||
<string name="rate_8000">8 kHz</string>
|
||||
<string name="rate_16000">16 kHz</string>
|
||||
<string name="rate_32000">32 kHz</string>
|
||||
<string name="rate_44100">44.1 kHz</string>
|
||||
<string name="rate_48000">48 kHz</string>
|
||||
<string name="channel_select">Channel Select</string>
|
||||
<string name="channel_default">Default</string>
|
||||
<string name="channel_first">First</string>
|
||||
<string name="channel_second">Second</string>
|
||||
<string name="channel_summation">Summation</string>
|
||||
<string name="channel_analytic">Analytic</string>
|
||||
<string name="audio_source">Audio Source</string>
|
||||
<string name="source_default">Default</string>
|
||||
<string name="source_microphone">Microphone</string>
|
||||
<string name="source_camcorder">Camcorder</string>
|
||||
<string name="source_voice_recognition">Voice Recognition</string>
|
||||
<string name="source_unprocessed">Unprocessed</string>
|
||||
<string name="audio_init_failed">Audio init failed</string>
|
||||
<string name="audio_setup_failed">Audio setup failed</string>
|
||||
<string name="audio_permission_denied">Audio permission denied</string>
|
||||
<string name="audio_recording_error">Audio recording error</string>
|
||||
<string name="scope_description">Visualization of audio signal</string>
|
||||
<string name="night_mode">Night Mode</string>
|
||||
<string name="enable">Enable</string>
|
||||
<string name="disable">Disable</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.Robot36" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<style name="Base.Theme.Robot36" parent="Theme.Material3.DayNight">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue