Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-24 08:57:51 +01:00
parent 495cb787f7
commit 2fb891f849
90 changed files with 10953 additions and 2 deletions

1
app/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

45
app/build.gradle Normal file
View file

@ -0,0 +1,45 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 32
defaultConfig {
android.defaultConfig.vectorDrawables.useSupportLibrary = true
applicationId "com.tunerly"
minSdkVersion 16
targetSdkVersion 32
versionCode 8
versionName "1.0.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'com.akexorcist:localization:1.2.9'
implementation files('libs/TarsosDSP-2.4.jar')
implementation 'androidx.preference:preference-ktx:1.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("org.jetbrains.kotlin:kotlin-reflect:1.5.0")
}

BIN
app/libs/TarsosDSP-2.4.jar Normal file

Binary file not shown.

21
app/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,24 @@
package com.example.tuner
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.tuner", appContext.packageName)
}
}

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tuner">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:allowBackup="true"
android:configChanges="uiMode"
android:fullBackupContent="true"
android:icon="@mipmap/logo"
android:label="@string/app_name"
android:roundIcon="@mipmap/logo"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="com.tunerly.SettingsActivity"
android:label="@string/title_activity_settings" />
<activity
android:name="com.tunerly.AboutActivity"
android:label="@string/title_activity_about" />
<activity
android:name="com.tunerly.MainActivity"
android:screenOrientation="portrait"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,36 @@
package com.tunerly
import android.os.Bundle
import android.view.MenuItem
import com.akexorcist.localizationactivity.ui.LocalizationActivity
import com.example.tuner.R
import com.example.tuner.databinding.ActivityAboutBinding
class AboutActivity : LocalizationActivity() {
private lateinit var binding: ActivityAboutBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAboutBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
setSupportActionBar(binding.toolbar)
supportActionBar?.title = getString(R.string.about)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val versionName: String = packageManager.getPackageInfo(packageName, 0).versionName
binding.versionTextView.text = versionName
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
return true
}
}
return super.onOptionsItemSelected(item)
}
}

View file

@ -0,0 +1,34 @@
package com.tunerly
import android.app.AlertDialog
import android.app.Dialog
import android.os.Build
import android.os.Bundle
import android.text.Html
import android.text.Spanned
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import com.example.tuner.R
class Dialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder: AlertDialog.Builder = AlertDialog.Builder(activity)
val title: String = getString(R.string.popup_title)
val text: String = getString(R.string.popup)
val ok: String = getString(R.string.ok)
builder.setTitle(title)
builder.setMessage(getSpannedText(text))
builder.setPositiveButton(ok) { _, _ ->
}
return builder.create()
}
private fun getSpannedText(text: String): Spanned? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(text, Html.FROM_HTML_MODE_COMPACT)
} else {
HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
}
}

View file

@ -0,0 +1,362 @@
package com.tunerly
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.*
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.TextView
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.PermissionChecker
import androidx.core.graphics.BlendModeColorFilterCompat
import androidx.core.graphics.BlendModeCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.fragment.app.DialogFragment
import androidx.preference.PreferenceManager
import be.tarsos.dsp.AudioDispatcher
import be.tarsos.dsp.AudioProcessor
import be.tarsos.dsp.io.android.AudioDispatcherFactory
import be.tarsos.dsp.pitch.PitchDetectionHandler
import be.tarsos.dsp.pitch.PitchProcessor
import com.akexorcist.localizationactivity.core.LocalizationApplicationDelegate
import com.akexorcist.localizationactivity.ui.LocalizationActivity
import com.example.tuner.R
import com.example.tuner.databinding.ActivityMainBinding
import java.util.*
import kotlin.math.min
class MainActivity : LocalizationActivity(), MyCallback {
private lateinit var binding: ActivityMainBinding
private val prefLastInstrument = "last_instrument"
private val prefLastTuning = "last_tuning"
private val processing = PitchProcessing(this@MainActivity)
private val sampleRate = 44100
private val recordOverlaps = 3072
private val localizationDelegate = LocalizationApplicationDelegate()
private var bufferSize: Int = 4096
private lateinit var instrumentSpinner: Spinner
private lateinit var tuningSpinner: Spinner
object CurTuning {
internal lateinit var curTuning: String
}
object CurInstrument {
internal lateinit var curInstrument: String
}
override fun onCreate(savedInstanceState: Bundle?) {
// ask for microphone permissions
if (ContextCompat.checkSelfPermission(
this@MainActivity,
Manifest.permission.RECORD_AUDIO
)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO),
1234
)
}
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
// load current state of dark mode
val isNightMode: Boolean = preferences.getBoolean("dark_theme", false)
if (isNightMode) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setTheme(R.style.AppTheme)
setContentView(view)
// keep screen on
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
// initializing instrument spinner
instrumentSpinner = findViewById(R.id.instrument_spinner)
ArrayAdapter.createFromResource(
this,
R.array.instruments_array,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
instrumentSpinner.adapter = adapter
}
instrumentSpinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>,
view: View?, pos: Int, id: Long
) {
CurInstrument.curInstrument = instrumentSpinner.getItemAtPosition(pos).toString()
when (parent.getItemAtPosition(pos).toString()) {
getString(R.string.guitar) -> {
tuningSpinner.visibility = View.VISIBLE
ArrayAdapter.createFromResource(
this@MainActivity,
R.array.tuning_array_guitar,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
tuningSpinner.adapter = adapter
}
}
getString(R.string.bass) -> {
tuningSpinner.visibility = View.VISIBLE
ArrayAdapter.createFromResource(
this@MainActivity,
R.array.tuning_array_bass,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
tuningSpinner.adapter = adapter
}
}
getString(R.string.ukulele) -> {
tuningSpinner.visibility = View.VISIBLE
ArrayAdapter.createFromResource(
this@MainActivity,
R.array.tuning_array_ukulele,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
tuningSpinner.adapter = adapter
}
}
getString(R.string.cuatro) -> {
tuningSpinner.visibility = View.VISIBLE
ArrayAdapter.createFromResource(
this@MainActivity,
R.array.tuning_array_cuatro,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
tuningSpinner.adapter = adapter
}
}
getString(R.string.chromatic) -> tuningSpinner.visibility = View.GONE
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
// initializing tuning spinner
tuningSpinner = findViewById(R.id.tuning_spinner)
ArrayAdapter.createFromResource(
this,
R.array.tuning_array_guitar,
android.R.layout.simple_spinner_dropdown_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
tuningSpinner.adapter = adapter
}
tuningSpinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?, pos: Int, id: Long
) {
CurTuning.curTuning = tuningSpinner.getItemAtPosition(pos).toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// Do nothing.
}
}
// menu
setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
// annotation dialog
val annotation = findViewById<View>(R.id.annotation) as TextView
annotation.setOnClickListener {
val dialog: DialogFragment = Dialog()
dialog.show(supportFragmentManager, "MyDialogFragmentTag")
}
val permission: Int = PermissionChecker.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
)
if (permission == PermissionChecker.PERMISSION_GRANTED) {
audioProcessing()
}
// load last state of the spinners
instrumentSpinner.setSelection(
min(preferences.getInt(prefLastInstrument, 0), instrumentSpinner.adapter.count - 1))
instrumentSpinner.post { // Give time to the instrumentSpinner to trigger its onItemSelected
tuningSpinner.post { // Give time to the to tuningSpinner to actually be updated
tuningSpinner.setSelection(
min(preferences.getInt(prefLastTuning, 0), tuningSpinner.adapter.count - 1))
}
}
}
private fun audioProcessing() {
// detecting frequencies through microphone
val dispatcher: AudioDispatcher =
AudioDispatcherFactory.fromDefaultMicrophone(sampleRate, bufferSize, recordOverlaps)
val pdh = PitchDetectionHandler { res, _ ->
val pitchInHz: Float = res.pitch
val probability: Float = res.probability
if (pitchInHz > -1) {
runOnUiThread { processing.tune(pitchInHz, probability)}
}
}
val pitchProcessor: AudioProcessor =
PitchProcessor(
PitchProcessor.PitchEstimationAlgorithm.FFT_YIN,
sampleRate.toFloat(), bufferSize, pdh
)
dispatcher.addAudioProcessor(pitchProcessor)
val audioThread = Thread(dispatcher, "Audio Thread")
audioThread.start()
}
// set language to default phone language
override fun attachBaseContext(newBase: Context) {
localizationDelegate.setDefaultLanguage(newBase, Locale.getDefault())
super.attachBaseContext(localizationDelegate.attachBaseContext(newBase))
}
// permission handling
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1234 -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
audioProcessing()
} else {
Log.d("TAG", "permission denied by user")
}
return
}
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.menu, menu)
return true
}
override fun onStop() {
super.onStop()
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putInt(prefLastInstrument, instrumentSpinner.selectedItemPosition)
.putInt(prefLastTuning, tuningSpinner.selectedItemPosition)
.apply()
}
// Items in menu
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.settings) {
val myIntent = Intent(this@MainActivity, SettingsActivity::class.java)
this@MainActivity.startActivity(myIntent)
return true
}
if (id == R.id.about) {
val myIntent = Intent(this@MainActivity, AboutActivity::class.java)
this@MainActivity.startActivity(myIntent)
return true
}
return super.onOptionsItemSelected(item)
}
override fun colorTuned(tuningDirection: String) {
var colorTop = R.color.colorControlNormal
var colorBottom = R.color.colorControlNormal
when (tuningDirection) {
"none" -> {
colorTop = R.color.colorTuned
colorBottom = R.color.colorTuned
}
"up" -> {
colorTop = R.color.colorOutOfTune
colorBottom = R.color.colorControlNormal
}
"down" -> {
colorTop = R.color.colorControlNormal
colorBottom = R.color.colorOutOfTune
}
}
val drawableUp = DrawableCompat.wrap(
ContextCompat.getDrawable(
this,
R.drawable.ic_play_arrow
)!!
)
binding.up.setImageDrawable(drawableUp)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
DrawableCompat.setTint(drawableUp, ContextCompat.getColor(this, colorTop))
} else {
drawableUp.mutate().colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
colorTop,
BlendModeCompat.SRC_ATOP
)
}
val drawableDown = DrawableCompat.wrap(
ContextCompat.getDrawable(
this,
R.drawable.ic_play_arrow
)!!
)
binding.down.setImageDrawable(drawableDown)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
DrawableCompat.setTint(drawableDown, ContextCompat.getColor(this, colorBottom))
} else {
drawableDown.mutate().colorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(
colorBottom,
BlendModeCompat.SRC_ATOP
)
}
}
override fun updateNote(note: String?) {
binding.noteText.gravity = Gravity.CENTER
binding.noteText.text = note
}
// set size of note displayed
fun noteSize() {
if (binding.noteText.text in arrayOf(
"A", "A#", "Bb", "B", "C", "C#", "Db", "D",
"D#", "Eb", "E", "F", "F#", "Gb", "G", "G#", "Ab"
)) {
binding.noteText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 280F)
}
}
}

View file

@ -0,0 +1,6 @@
package com.tunerly
interface MyCallback {
fun updateNote(note: String?)
fun colorTuned(tuningDirection: String)
}

View file

@ -0,0 +1,241 @@
package com.tunerly
import com.example.tuner.R
import kotlin.math.round
import kotlin.math.log2
import kotlin.math.abs
import kotlin.math.pow
class PitchProcessing(callback: MyCallback?) {
private var myCallback: MyCallback? = callback
private val allNotes = arrayOf("A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#")
private val pitchMap = mapOf(16.35F to "C", 17.32F to "C#", 18.35F to "D", 19.45F to "D#",
20.60F to "E", 21.83F to "F", 23.12F to "F#", 24.50F to "G", 25.96F to "G#", 27.50F to "A",
29.14F to "A#", 30.87F to "B", 32.70F to "C", 34.65F to "C#", 36.71F to "D", 38.90F to "D#",
41.20F to "E", 43.65F to "F", 46.25F to "F#", 49.00F to "G", 51.91F to "G#", 55.00F to "A",
58.27F to "A#", 61.74F to "B", 65.40F to "C", 69.30F to "Db", 73.42F to "D", 77.78F to "Eb",
82.41F to "E", 87.31F to "F", 92.50F to "F#", 98.00F to "G", 103.83F to "Ab", 110.00F to "A",
116.54F to "A#", 123.47F to "B", 130.81F to "C", 138.59F to "Db", 146.83F to "D",
155.56F to "D#", 164.81F to "E", 174.61F to "F", 185.00F to "Gb", 196.00F to "G",
207.65F to "G#", 220.00F to "A", 233.08F to "Bb", 246.94F to "B", 261.63F to "C",
277.18F to "C#", 293.66F to "D", 311.13F to "Eb", 329.63F to "E", 349.23F to "F",
370.00F to "Gb", 392.00F to "G", 415.30F to "G#", 440.00F to "A", 466.16F to "A#",
493.88F to "B", 523.25F to "C", 554.37F to "C#", 587.33F to "D", 622.25F to "D#",
659.26F to "E", 698.46F to "F", 739.99F to "F#", 784.00F to "G", 830.61F to "G#",
880.00F to "A", 932.33F to "A#", 987.76F to "B", 1046.50F to "C", 1108.73F to "C#",
1174.66F to "D", 1244.50F to "D#", 1318.51F to "E", 1396.91F to "F", 1479.98F to "F#",
1567.98F to "G", 1661.22F to "G#", 1760.00F to "A", 1864.66F to "A#", 1975.53F to "B",
2093.01F to "C", 2217.46F to "C#", 2349.32F to "D", 2489.02F to "D#", 2637.02F to "E",
2793.83F to "F", 2959.96F to "F#", 3135.96F to "G", 3322.44F to "G#", 3520.00F to "A",
3729.31F to "A#", 3951.07F to "B", 4186.01F to "C")
private val tuningMap = mapOf(
"Standard" to TuningData.GuitarStandard,
"Стандарт" to TuningData.GuitarStandard,
"Estandarra" to TuningData.GuitarStandard,
"Standardi" to TuningData.GuitarStandard,
"7 String" to TuningData.GuitarSeven,
"7 Saiten" to TuningData.GuitarSeven,
"7 струн" to TuningData.GuitarSeven,
"7 soka" to TuningData.GuitarSeven,
"7 Kielinen" to TuningData.GuitarSeven,
"7 cuerda" to TuningData.GuitarSeven,
"8 String" to TuningData.GuitarEight,
"8 Saiten" to TuningData.GuitarEight,
"8 струн" to TuningData.GuitarEight,
"8 soka" to TuningData.GuitarEight,
"8 Kielinen" to TuningData.GuitarEight,
"8 cuerda" to TuningData.GuitarEight,
"E-Flat" to TuningData.GuitarEFlat,
"Eb" to TuningData.GuitarEFlat,
"E-bemol" to TuningData.GuitarEFlat,
"Full step down" to TuningData.GuitarFullStepDown,
"Ganzton tiefer" to TuningData.GuitarFullStepDown,
"Koko sävy alempi" to TuningData.GuitarFullStepDown,
"На целый тон ниже" to TuningData.GuitarFullStepDown,
"Tonu osoa baxuagoa" to TuningData.GuitarFullStepDown,
"Todo el tono más bajo" to TuningData.GuitarFullStepDown,
"Drop D" to TuningData.GuitarDropD,
"Drop Db" to TuningData.GuitarDropDb,
"Double Drop D" to TuningData.GuitarDoubleDropD,
"Drop D bikoitza" to TuningData.GuitarDoubleDropD,
"DADGAD" to TuningData.GuitarDADGAD,
"Open D" to TuningData.GuitarOpenD,
"Avoin D" to TuningData.GuitarOpenD,
"D irekia" to TuningData.GuitarOpenD,
"Open A" to TuningData.GuitarOpenA,
"Avoin A" to TuningData.GuitarOpenA,
"A irekia" to TuningData.GuitarOpenA,
"Open E" to TuningData.GuitarOpenE,
"Avoin E" to TuningData.GuitarOpenE,
"E irekia" to TuningData.GuitarOpenE,
"Open G" to TuningData.GuitarOpenG,
"Avoin G" to TuningData.GuitarOpenG,
"G irekia" to TuningData.GuitarOpenG,
"Open B" to TuningData.GuitarOpenB,
"Avoin B" to TuningData.GuitarOpenB,
"B irekia" to TuningData.GuitarOpenB,
"4 String" to TuningData.BassStandard4,
"4 Saiten" to TuningData.BassStandard4,
"4 струн" to TuningData.BassStandard4,
"4 soka" to TuningData.BassStandard4,
"4 Kielinen" to TuningData.BassStandard4,
"4 cuerda" to TuningData.BassStandard4,
"5 String" to TuningData.BassStandard5,
"5 Saiten" to TuningData.BassStandard5,
"5 струн" to TuningData.BassStandard5,
"5 soka" to TuningData.BassStandard5,
"5 Kielinen" to TuningData.BassStandard5,
"5 cuerda" to TuningData.BassStandard5,
"6 String" to TuningData.BassStandard6,
"6 Saiten" to TuningData.BassStandard6,
"6 струн" to TuningData.BassStandard6,
"6 soka" to TuningData.BassStandard6,
"6 Kielinen" to TuningData.BassStandard6,
"6 cuerda" to TuningData.BassStandard6,
"Drop-D" to TuningData.BassDropD,
"D Standard" to TuningData.BassDStandard,
"D Стандарт" to TuningData.BassDStandard,
"D estandarra" to TuningData.BassDStandard,
"D Standardi" to TuningData.BassDStandard,
"Drop C" to TuningData.BassDropC,
"C (Standard)" to TuningData.UkuleleStandard,
"C (Стандарт)" to TuningData.UkuleleStandard,
"C (estandarra)" to TuningData.UkuleleStandard,
"C (Standardi)" to TuningData.UkuleleStandard,
"D (Traditional)" to TuningData.UkuleleTraditional,
"D (Traditionell)" to TuningData.UkuleleTraditional,
"D (Традиционный)" to TuningData.UkuleleTraditional,
"D (tradizionala)" to TuningData.UkuleleTraditional,
"D (Perinteinen)" to TuningData.UkuleleTraditional,
"D (Tradicional)" to TuningData.UkuleleTraditional,
"Baritone" to TuningData.UkuleleBaritone,
"Bariton" to TuningData.UkuleleBaritone,
"Баритон" to TuningData.UkuleleBaritone,
"Baritonoa" to TuningData.UkuleleBaritone,
"Baritoni" to TuningData.UkuleleBaritone,
"Bass" to TuningData.UkuleleBass,
"бас" to TuningData.UkuleleBass,
"Baxua" to TuningData.UkuleleBass,
"Basso" to TuningData.UkuleleBass,
"C-Standard" to TuningData.CuatroC,
"C-estandarra" to TuningData.CuatroC,
"C-Standardi" to TuningData.CuatroC,
"C-Стандарт" to TuningData.CuatroC,
"D-Standard" to TuningData.CuatroD,
"D-estandarra" to TuningData.CuatroD,
"D-Standardi" to TuningData.CuatroD,
"D-Стандарт" to TuningData.CuatroD
)
fun tune(pitchInHz: Float, probability: Float) {
if (MainActivity.CurInstrument.curInstrument == (myCallback as MainActivity).getString(R.string.chromatic)) {
if (probability > 0.92) {
myCallback?.updateNote(closestNote(pitchInHz))
tuningDirection(pitchInHz, closestPitch(pitchInHz))
}
} else {
// stores pitches in Hz of current selected tuning
val pitches = (tuningMap[MainActivity.CurTuning.curTuning] ?: error("")).frequencies
(myCallback as MainActivity).noteSize()
if (tuningMap.keys.contains(MainActivity.CurTuning.curTuning)) {
val stringPitch = closestString(pitchInHz, pitches)
if (probability > 0.92) {
myCallback?.updateNote(pitchMap.getValue(stringPitch))
tuningDirection(pitchInHz, stringPitch)
}
}
}
}
private fun tuningDirection(curPitch: Float, toPitch: Float) {
var tuneUp = true
var tuneDown = true
// calculate interval in cents from hz given
val cents : Float = 1200 * log2(toPitch / curPitch)
if (cents > 10 || cents < -10) {
if (cents > 10) {
tuneUp = true
tuneDown = false
}
else if (cents < -10) {
tuneUp = false
tuneDown = true
}
}
else {
tuneUp = false
tuneDown = false
}
if (!tuneUp && !tuneDown) {
myCallback?.colorTuned("none")
}
else if (tuneUp && !tuneDown) {
myCallback?.colorTuned("up")
}
else if (!tuneUp && tuneDown){
myCallback?.colorTuned("down")
}
}
/**
* determine which string current note is closest to
* @return Float (Frequency in Hz)
*/
private fun closestString(pitchInHz: Float, tuning: FloatArray): Float {
var difference = abs(tuning[0] - pitchInHz)
var idx = 0
for (c in 1 until tuning.size) {
val cdifference = abs(tuning[c] - pitchInHz)
if (cdifference < difference) {
idx = c
difference = cdifference
}
}
return tuning[idx]
}
/** detects closest note in A = 440 with equal temperament formula:
* pitch(i) = pitch(0) * 2^(halfSteps/12)
* therefore formula to derive interval between two pitches:
* i = 12 * log2 * (pitch(i)/pitch(o))
*/
private fun closestNote(pitchInHz: Float): String {
(myCallback as MainActivity).noteSize()
val i = (round(log2(pitchInHz / 440) * 12)).toInt()
// floorMod implementation to prevent ArrayIndexOutOfBoundException
return allNotes[(i % 12 + 12) % 12]
}
private fun closestPitch(pitchInHz: Float): Float {
val i = (round(log2(pitchInHz / 440) * 12)).toInt()
val closestPitch = 440 * 2.toDouble().pow(i.toDouble() / 12)
return closestPitch.toFloat()
}
}

View file

@ -0,0 +1,123 @@
package com.tunerly
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import com.akexorcist.localizationactivity.ui.LocalizationActivity
import com.example.tuner.R
import com.example.tuner.databinding.ActivitySettingsBinding
class SettingsActivity : LocalizationActivity() {
private lateinit var binding: ActivitySettingsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.settings, SettingsFragment())
.commit()
}
setSupportActionBar(binding.toolbar)
supportActionBar?.title = getString(R.string.settings)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
onBackPressed()
return true
}
}
return super.onOptionsItemSelected(item)
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
// theme
val switchPreferenceCompat: SwitchPreferenceCompat? =
findPreference("dark_theme")
switchPreferenceCompat!!.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
var isChecked = false
if (newValue is Boolean) isChecked = newValue
if (isChecked) {
preferenceManager.sharedPreferences?.edit()
?.putBoolean(getString(R.string.dark_theme), true)?.apply()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else {
preferenceManager.sharedPreferences?.edit()
?.putBoolean(getString(R.string.dark_theme), false)?.apply()
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
true
}
// language
val listPreference =
findPreference<Preference>(getString(R.string.language_preference)) as ListPreference?
listPreference?.setOnPreferenceChangeListener { preference, newValue ->
if (preference is ListPreference) {
val index = preference.findIndexOfValue(newValue.toString())
val locale = preference.entryValues[index]
if (locale == "de") {
(activity as SettingsActivity).changeLanguageGer()
}
if (locale == "en") {
(activity as SettingsActivity).changeLanguageEn()
}
if (locale == "ru") {
(activity as SettingsActivity).changeLanguageRu()
}
if (locale == "eu") {
(activity as SettingsActivity).changeLanguageEu()
}
if (locale == "fi") {
(activity as SettingsActivity).changeLanguageFi()
}
if (locale == "es") {
(activity as SettingsActivity).changeLanguageEs()
}
}
true
}
}
}
fun changeLanguageGer() {
setLanguage("de")
}
fun changeLanguageEn() {
setLanguage("en")
}
fun changeLanguageRu() {
setLanguage("ru")
}
fun changeLanguageEu() {
setLanguage("eu")
}
fun changeLanguageFi() {
setLanguage("fi")
}
fun changeLanguageEs() {
setLanguage("es")
}
}

View file

@ -0,0 +1,35 @@
package com.tunerly
enum class TuningData(vararg f: Float) {
// Guitar Tunings
GuitarStandard(82.41F, 110.00F, 146.83F, 196.00F, 246.94F, 329.63F),
GuitarSeven(61.74F, 82.41F, 110.00F, 146.83F, 196.00F, 246.94F, 329.63F),
GuitarEight(46.25F, 61.74F, 82.41F, 110.00F, 146.83F, 196.00F, 246.94F, 329.63F),
GuitarEFlat(77.78F, 103.83F, 138.59F, 185.00F, 233.08F, 311.13F),
GuitarFullStepDown(73.42F, 98.00F, 130.81F, 174.61F, 220.00F, 293.66F),
GuitarDropD(73.42F, 110.00F, 146.83F, 196.00F, 246.94F, 329.63F),
GuitarDropDb(69.30F, 103.83F, 138.59F, 185.00F, 233.08F, 311.13F),
GuitarDoubleDropD(73.42F, 110.00F, 146.83F, 196.00F, 246.94F, 293.66F),
GuitarDADGAD(73.42F, 110.00F, 146.83F, 196.00F, 220.00F, 329.63F),
GuitarOpenD(73.42F, 110.00F, 146.83F, 185.00F, 220.00F, 329.63F),
GuitarOpenA(82.41F, 110.00F, 138.59F, 164.81F, 220.00F, 329.63F),
GuitarOpenE(82.41F, 123.47F, 164.81F, 207.65F, 246.94F, 329.63F),
GuitarOpenG(77.78F, 98.00F, 146.83F, 196.00F, 246.94F, 293.66F),
GuitarOpenB(61.74F, 92.50F, 123.47F, 185.00F, 246.94F, 311.13F),
// Bass Tunings
BassStandard4(41.20F, 55.00F, 73.42F, 98.00F),
BassStandard5(30.87F, 41.20F, 55.00F, 73.42F, 98.00F),
BassStandard6(30.87F, 41.20F, 55.00F, 73.42F, 98.00F, 130.81F),
BassDropD(36.71F, 55.00F, 73.42F, 98.00F),
BassDStandard(36.71F, 49.00F, 65.40F, 87.31F),
BassDropC(32.70F, 49.00F, 65.40F, 87.31F),
// Ukulele Tunings
UkuleleStandard(392.00F, 261.63F, 329.63F, 440.00F),
UkuleleTraditional(440.00F, 293.66F, 370.00F, 493.88F),
UkuleleBaritone(146.83F, 196.00F, 246.94F, 329.63F),
UkuleleBass(41.20F, 55.00F, 73.42F, 98.00F),
CuatroC(196.00F, 261.63F, 329.63F, 220.00F),
CuatroD(220.00F, 293.66F, 370.00F, 246.94F);
val frequencies: FloatArray = f
}

View file

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View file

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,152 @@
<LinearLayout 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"
android:orientation="vertical"
android:background="?attr/colorPrimary"
android:parentActivityName="com.example.tuner.MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/about"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contactSeparator"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/contact"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="0dp" />
<TextView
android:id="@+id/contactText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:lineSpacingExtra="3dp"
android:paddingStart="0dp"
android:paddingEnd="30dp"
android:text="@string/contact_text"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contactSeparator" />
<TextView
android:id="@+id/contactEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingStart="0dp"
android:paddingEnd="30dp"
android:autoLink="email"
android:text="@string/contact_email"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contactText" />
<TextView
android:id="@+id/privacyPolicySeparator"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/privacy_policy"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/contactEmail" />
<TextView
android:id="@+id/privacyPolicyLink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:autoLink="web"
android:lineSpacingExtra="3dp"
android:paddingStart="0dp"
android:paddingEnd="30dp"
android:text="@string/privacy_policy_link"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/privacyPolicySeparator" />
<TextView
android:id="@+id/githubSeparator"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/github"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/privacyPolicyLink" />
<TextView
android:id="@+id/github"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:lineSpacingExtra="3dp"
android:paddingStart="0dp"
android:paddingEnd="30dp"
android:text="@string/github_text"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/githubSeparator" />
<TextView
android:id="@+id/githubLink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:lineSpacingExtra="3dp"
android:text="@string/github_link"
android:paddingStart="0dp"
android:paddingEnd="30dp"
android:autoLink="web"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/github" />
<TextView
android:id="@+id/versionSeparator"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/version"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/githubLink" />
<TextView
android:id="@+id/versionTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="3dp"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/versionSeparator" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</LinearLayout>

View file

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/tuner_area"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorPrimary"
android:minHeight="?actionBarSize"
tools:context="com.tunerly.MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Spinner
android:id="@+id/instrument_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="19dp"
android:layout_marginTop="4dp"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toStartOf="@id/toolbar"
app:layout_constraintTop_toTopOf="parent" />
<Spinner
android:id="@+id/tuning_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toEndOf="@+id/toolbar"
app:layout_constraintStart_toEndOf="@+id/instrument_spinner"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/noteText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/pluck_a_string"
android:textSize="50dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
tools:ignore="SpUsage" />
<ImageView
android:id="@+id/down"
android:layout_width="79dp"
android:layout_height="128dp"
android:contentDescription="@string/tune_down"
android:rotation="90"
android:src="@drawable/ic_play_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.834"
app:tint="@color/colorControlNormal" />
<ImageView
android:id="@+id/up"
android:layout_width="79dp"
android:layout_height="128dp"
android:contentDescription="@string/tune_up"
android:rotation="270"
android:src="@drawable/ic_play_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.159"
app:tint="@color/colorControlNormal" />
<TextView
android:id="@+id/annotation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="55dp"
android:layout_marginBottom="27dp"
android:clickable="true"
android:focusable="true"
android:text="@string/annotation"
android:textSize="50dp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="SpUsage" />
<ImageView
android:id="@+id/logo"
android:layout_width="89dp"
android:layout_height="187dp"
android:layout_marginStart="30dp"
android:contentDescription="@string/logo"
android:translationY="37dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:srcCompat="@drawable/logo_final" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,25 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?attr/colorPrimary"
android:parentActivityName="com.example.tuner.MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/settings"
android:title="@string/settings" />
<item
android:id="@+id/about"
android:title="@string/about" />
</menu>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pluck_a_string">Bereit</string>
<string name="tune_down">Hochstimmen</string>
<string name="tune_up">Runterstimmen</string>
<string name="preference_title">Sprache</string>
<string name="popup"><![CDATA[
<p>Blauer Pfeil: Stimme in die Richtung, in die der Pfeil zeigt</p><br>
Beide Pfeile grün: Dein Instrument ist gestimmt</p>
]]></string>
<string name="settings">Einstellungen</string>
<string name="about">Über</string>
<string name="contact">Kontakt</string>
<string name="privacy_policy">Datenschutz-Bestimmung</string>
<string name="privacy_policy_text">"Die Datenschutz-Bestimmung findest Du hier "</string>
<string name="github_text">"Tunerly ist eine Open Source App. Das Projekt findest Du hier auf Github "</string>
<string name="contact_text">Solltest Du irgendwelche Fragen oder Vorschläge haben, oder hast Du einen Fehler gefunden, kannst Du mich hier kontaktieren </string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>Gitarre</item>
<item>Bass</item>
<item>Ukulele</item>
<item>Cuatro</item>
<item>Chromatisch</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Standard</item>
<item>7 Saiten</item>
<item>8 Saiten</item>
<item>Eb</item>
<item>Ganzton tiefer</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Double Drop D</item>
<item>DADGAD</item>
<item>Open D</item>
<item>Open A</item>
<item>Open E</item>
<item>Open G</item>
<item>Open B</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 Saiten</item>
<item>5 Saiten</item>
<item>6 Saiten</item>
<item>Drop-D</item>
<item>D Standard</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (Standard)</item>
<item>D (Traditionell)</item>
<item>Bariton</item>
<item>Bass</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-Standard</item>
<item>D-Standard</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>Baskisch</item>
<item>Englisch</item>
<item>Finnisch</item>
<item>Deutsch</item>
<item>Russisch</item>
<item>Spanisch</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
<item>es</item>
</string-array>
<string name="switch_theme">Dark Theme</string>
<string name="popup_title">Info</string>
<string name="ok">OK</string>
<string name="guitar">Gitarre</string>
<string name="bass">Bass</string>
<string name="ukulele">Ukulele</string>
<string name="cuatro">Cuatro</string>
<string name="chromatic">Chromatisch</string>
<string name="version" translatable="false">Version</string>
</resources>

View file

@ -0,0 +1,112 @@
<resources>
<!-- General -->
<string name="app_name" translatable="false">Tunerly</string>
<string name="pluck_a_string">Toca</string>
<string name="tune_down">Baja la afinación</string>
<string name="tune_up">Sube la afinación</string>
<string name="annotation" translatable="false">\?</string>
<string name="logo" translatable="false">logo</string>
<string name="switch_theme">Tema oscuro</string>
<string name="preference_title">Idioma</string>
<string name="popup"><![CDATA[
<p>Flecha azul: Sintoniza en la dirección que señala la flecha</p><br>
Ambas flechas verdes: Estás en sintonía</p>
]]></string>
<string name="popup_title">Información</string>
<string name="ok">OK</string>
<!-- Settings fields -->
<string name="settings">Ajustes</string>
<string name="about">Acerca de</string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>@string/guitar</item>
<item>@string/bass</item>
<item>@string/ukulele</item>
<item>@string/cuatro</item>
<item>@string/chromatic</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Standard</item>
<item>7 cuerda</item>
<item>8 cuerda</item>
<item>E-Flat</item>
<item>Todo el tono más bajo</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Double Drop D</item>
<item>DADGAD</item>
<item>Open D</item>
<item>Open A</item>
<item>Open E</item>
<item>Open G</item>
<item>Open B</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 cuerda</item>
<item>5 cuerda</item>
<item>6 cuerda</item>
<item>Drop-D</item>
<item>D Standard</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (Standard)</item>
<item>D (Tradicional)</item>
<item>Baritone</item>
<item>Bass</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-Standard</item>
<item>D-Standard</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Settings -->
<string name="title_activity_settings" translatable="false">SettingsActivity</string>
<string name="dark_theme" translatable="false">dark_theme</string>
<!-- About -->
<string name="title_activity_about" translatable="false">AboutActivity</string>
<string name="contact">Contacto</string>
<string name="contact_text">Si tiene alguna pregunta, sugerencia o desea reportar algún error, puede contactarme por </string>
<string name="contact_email" translatable="false">tunerlyapp@gmail.com</string>
<string name="privacy_policy">Política de privacidad</string>
<string name="privacy_policy_text">Puede encontrar la política de privacidad aquí</string>
<string name="privacy_policy_link" translatable="false">https://github.com/brianhorn/Tunerly/blob/master/privacy_policy.md</string>
<string name="github" translatable="false">Github</string>
<string name="github_text">Tunerly es una aplicación de Código Abierto. Puede encontrar el proyecto en GitHub aquí</string>
<string name="github_link" translatable="false">https://github.com/brianhorn/Tunerly</string>
<string name="version">Versión</string>
<string name="guitar">Guitarra</string>
<string name="bass">Bajo</string>
<string name="ukulele">Ukulele</string>
<string name="cuatro">Cuatro</string>
<string name="chromatic">Cromático</string>
<string name="language_preference" translatable="false">language_preference</string>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>Español</item>
<item>Euskera</item>
<item>Inglés</item>
<item>Finlandés</item>
<item>Alemán</item>
<item>Ruso</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>es</item>
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
</string-array>
</resources>

View file

@ -0,0 +1,112 @@
<resources>
<!-- General -->
<string name="app_name" translatable="false">Tunerly</string>
<string name="pluck_a_string">Jo</string>
<string name="tune_down">Jaitsi</string>
<string name="tune_up">Igo</string>
<string name="annotation" translatable="false">\?</string>
<string name="logo" translatable="false">logo</string>
<string name="switch_theme">Itxura iluna</string>
<string name="preference_title">Hizkuntza</string>
<string name="popup"><![CDATA[
<p>Gezi urdina: afinatu geziaren noranzkoan</p><br>
Bi geziak berde: afinatuta dago</p>
]]></string>
<string name="popup_title">Informazioa</string>
<string name="ok">ADOS</string>
<!-- Settings fields -->
<string name="settings">Ezarpenak</string>
<string name="about">Honi buruz</string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>@string/guitar</item>
<item>@string/bass</item>
<item>@string/ukulele</item>
<item>@string/cuatro</item>
<item>@string/chromatic</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Estandarra</item>
<item>7 soka</item>
<item>8 soka</item>
<item>E-bemol</item>
<item>Koko sävy alempi</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Drop D bikoitza</item>
<item> DADGAD</item>
<item>D irekia</item>
<item>A irekia</item>
<item>E irekia</item>
<item>G irekia</item>
<item>B irekia</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 soka</item>
<item>5 soka</item>
<item>6 soka</item>
<item>Drop-D</item>
<item>D estandarra</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (estandarra)</item>
<item>D (tradizionala)</item>
<item>Baritonoa</item>
<item>Baxua</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-estandarra</item>
<item>D-estandarra</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Settings -->
<string name="title_activity_settings" translatable="false">SettingsActivity</string>
<string name="dark_theme" translatable="false">dark_theme</string>
<!-- About -->
<string name="title_activity_about" translatable="false">AboutActivity</string>
<string name="contact">Kontaktua</string>
<string name="contact_text">Galderarik, iradokizunik edo berri emateko akatsik baduzu, helbide honetan kontaktatu nazakezu: </string>
<string name="contact_email" translatable="false">tunerlyapp@gmail.com</string>
<string name="privacy_policy">Pribatutasun gidalerroa</string>
<string name="privacy_policy_text">Pribatutasun gidalerroa hemen aurkitu dezakezu</string>
<string name="privacy_policy_link" translatable="false">https://github.com/brianhorn/Tunerly/blob/master/privacy_policy_en_de_rus_eu.md</string>
<string name="github" translatable="false">Github</string>
<string name="github_text">Tunerly kode irekiko aplikazioa da. Proiektua GitHuben aurkitu dezakezu</string>
<string name="github_link" translatable="false">https://github.com/brianhorn/Tunerly</string>
<string name="version">Bertsioa</string>
<string name="guitar">Gitarra</string>
<string name="bass">Baxua</string>
<string name="ukulele">Ukulelea</string>
<string name="cuatro">Cuatro</string>
<string name="chromatic">Kromatikoa</string>
<string name="language_preference" translatable="false">language_preference</string>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>Euskara</item>
<item>Ingelesa</item>
<item>Finlandiera</item>
<item>Alemana</item>
<item>Errusiera</item>
<item>Gaztelania</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
<item>es</item>
</string-array>
</resources>

View file

@ -0,0 +1,112 @@
<resources>
<!-- General -->
<string name="app_name" translatable="false">Tunerly</string>
<string name="pluck_a_string">Soita</string>
<string name="tune_down">Viritä matalammaksi</string>
<string name="tune_up">Viritä korkeammaksi</string>
<string name="annotation" translatable="false">\?</string>
<string name="logo" translatable="false">logo</string>
<string name="switch_theme">Tumma teema</string>
<string name="preference_title">Kieli</string>
<string name="popup"><![CDATA[
<p>Sininen nuoli: Viritä suuntaan, johon nuoli osoittaa</p><br>
Molemmat nuolet vihreitä: Olet vireessä</p>
]]></string>
<string name="popup_title">Ohje</string>
<string name="ok">Selvä</string>
<!-- Settings fields -->
<string name="settings">Asetukset</string>
<string name="about">Tietoja</string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>@string/guitar</item>
<item>@string/bass</item>
<item>@string/ukulele</item>
<item>@string/cuatro</item>
<item>@string/chromatic</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Standardi</item>
<item>7 Kielinen</item>
<item>8 Kielinen</item>
<item>E-Flat</item>
<item>Tonu osoa baxuagoa</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Double Drop D</item>
<item> DADGAD</item>
<item>Avoin D</item>
<item>Avoin A</item>
<item>Avoin E</item>
<item>Avoin G</item>
<item>Avoin B</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 Kielinen</item>
<item>5 Kielinen</item>
<item>6 Kielinen</item>
<item>Drop-D</item>
<item>D Standardi</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (Standardi)</item>
<item>D (Perinteinen)</item>
<item>Baritoni</item>
<item>Basso</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-Standardi</item>
<item>D-Standardi</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Settings -->
<string name="title_activity_settings" translatable="false">SettingsActivity</string>
<string name="dark_theme" translatable="false">dark_theme</string>
<!-- About -->
<string name="title_activity_about" translatable="false">AboutActivity</string>
<string name="contact">Yhteystiedot</string>
<string name="contact_text">Jos sinulla on kysyttävää, ehdotuksia tai ongelmia ilmoitattevaksi, voit laittaa sähköpostia osoitteeseen</string>
<string name="contact_email" translatable="false">tunerlyapp@gmail.com</string>
<string name="privacy_policy">Tietosuojakäytäntö</string>
<string name="privacy_policy_text">Tietosuojakäytäntö löytyy täältä</string>
<string name="privacy_policy_link" translatable="false">https://github.com/brianhorn/Tunerly/blob/master/privacy_policy_en_de_rus_eu.md</string>
<string name="github" translatable="false">Github</string>
<string name="github_text">Tunerly on avoimen lähdekoodin ohjelma. Löydät projektin Githubista täältä</string>
<string name="github_link" translatable="false">https://github.com/brianhorn/Tunerly</string>
<string name="version">Versio</string>
<string name="guitar">Kitara</string>
<string name="bass">Basso</string>
<string name="ukulele">Ukulele</string>
<string name="cuatro">Cuatro</string>
<string name="chromatic">Kromaattinen</string>
<string name="language_preference" translatable="false">language_preference</string>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>baski</item>
<item>Englanti</item>
<item>Suomalainen</item>
<item>Saksan kieli</item>
<item>Venäjän kieli</item>
<item>Espanja</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
<item>es</item>
</string-array>
</resources>

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="pluck_a_string">готов</string>
<string name="tune_down">Hochstimmen</string>
<string name="tune_up">Runterstimmen</string>
<string name="preference_title">язык</string>
<string name="popup"><![CDATA[
<p>Синяя стрелка: звук в том направлении,в котором стрелка указывает </p><br>
Обе стрелки зелёные: твой инструмент настроен </p>
]]></string>
<string name="settings">Настройки</string>
<string name="about">О нас</string>
<string name="privacy_policy">политика конфиденциальности</string>
<string name="privacy_policy_text">вы можете найти нашу политику конфиденциальности здесь</string>
<string name="github_text">Tunerly открытый источник арр. Проект ты найдёшь здесь Github</string>
<string name="contact_text">если у вас есть какие-либо вопросы или предложения, или вы обнаружили ошибку вы можете связаться со мной здесь</string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>Гитара</item>
<item>бас</item>
<item>Укулеле</item>
<item>Куатро</item>
<item>Хроматический</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Стандарт</item>
<item>7 струн</item>
<item>8 струн</item>
<item>Eb</item>
<item>На целый тон ниже</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Double Drop D</item>
<item>DADGAD</item>
<item>Open D</item>
<item>Open A</item>
<item>Open E</item>
<item>Open G</item>
<item>Open B</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 струн</item>
<item>5 струн</item>
<item>6 струн</item>
<item>Drop-D</item>
<item>D Стандарт</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (Стандарт)</item>
<item>D (Традиционный)</item>
<item>Баритон</item>
<item>бас</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-Стандарт</item>
<item>D-Стандарт</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>баскский</item>
<item>английский</item>
<item>финский</item>
<item>Немецкий</item>
<item>русский</item>
<item>испанский язык</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
<item>es</item>
</string-array>
<string name="switch_theme">"тёмная"</string>
<string name="popup_title">Информация</string>
<string name="ok">ОК</string>
<string name="contact">Контакт</string>
<string name="guitar">Гитара</string>
<string name="bass">бас</string>
<string name="ukulele">Укулеле</string>
<string name="cuatro">Куатро</string>
<string name="chromatic">Хроматический</string>
<string name="version">версия</string>
</resources>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorAccent">#000000</color>
<color name="textColorPrimary">#000000</color>
<color name="colorOutOfTune">#40C4FF</color>
<color name="colorTuned">#00E676</color>
<color name="colorControlNormal">#4F5B62</color>
</resources>

View file

@ -0,0 +1,112 @@
<resources>
<!-- General -->
<string name="app_name" translatable="false">Tunerly</string>
<string name="pluck_a_string">Play</string>
<string name="tune_down">Tune down</string>
<string name="tune_up">Tune up</string>
<string name="annotation" translatable="false">\?</string>
<string name="logo" translatable="false">logo</string>
<string name="switch_theme">Dark Theme</string>
<string name="preference_title">Language</string>
<string name="popup"><![CDATA[
<p>Blue arrow: Tune in the direction the arrow points to</p><br>
Both arrows green: You are in tune</p>
]]></string>
<string name="popup_title">Info</string>
<string name="ok">OK</string>
<!-- Settings fields -->
<string name="settings">Settings</string>
<string name="about">About</string>
<!-- Instrument Spinner-->
<string-array name="instruments_array">
<item>@string/guitar</item>
<item>@string/bass</item>
<item>@string/ukulele</item>
<item>@string/cuatro</item>
<item>@string/chromatic</item>
</string-array>
<!-- Tunings -->
<string-array name="tuning_array_guitar">
<item>Standard</item>
<item>7 String</item>
<item>8 String</item>
<item>E-Flat</item>
<item>Full step down</item>
<item>Drop D</item>
<item>Drop Db</item>
<item>Double Drop D</item>
<item> DADGAD</item>
<item>Open D</item>
<item>Open A</item>
<item>Open E</item>
<item>Open G</item>
<item>Open B</item>
</string-array>
<string-array name="tuning_array_bass">
<item>4 String</item>
<item>5 String</item>
<item>6 String</item>
<item>Drop-D</item>
<item>D Standard</item>
<item>Drop C</item>
</string-array>
<string-array name="tuning_array_ukulele">
<item>C (Standard)</item>
<item>D (Traditional)</item>
<item>Baritone</item>
<item>Bass</item>
</string-array>
<string-array name="tuning_array_cuatro">
<item>C-Standard</item>
<item>D-Standard</item>
</string-array>
<string-array name="chromatic">
<item> </item>
</string-array>
<!-- Settings -->
<string name="title_activity_settings" translatable="false">SettingsActivity</string>
<string name="dark_theme" translatable="false">dark_theme</string>
<!-- About -->
<string name="title_activity_about" translatable="false">AboutActivity</string>
<string name="contact">Contact</string>
<string name="contact_text">If you have any questions, suggestions or bugs to report, you can contact me at </string>
<string name="contact_email" translatable="false">tunerlyapp@gmail.com</string>
<string name="privacy_policy">Privacy Policy</string>
<string name="privacy_policy_text">Privacy Policy can be found here</string>
<string name="privacy_policy_link" translatable="false">https://github.com/brianhorn/Tunerly/blob/master/privacy_policy.md</string>
<string name="github" translatable="false">Github</string>
<string name="github_text">Tunerly is an Open Source app. You can find the project on Github here</string>
<string name="github_link" translatable="false">https://github.com/brianhorn/Tunerly</string>
<string name="version">Version</string>
<string name="guitar">Guitar</string>
<string name="bass">Bass</string>
<string name="ukulele">Ukulele</string>
<string name="cuatro">Cuatro</string>
<string name="chromatic">Chromatic</string>
<string name="language_preference" translatable="false">language_preference</string>
<!-- Language Preference -->
<string-array name="language_array" translatable="false">
<item>Basque</item>
<item>English</item>
<item>Finnish</item>
<item>German</item>
<item>Russian</item>
<item>Spanish</item>
</string-array>
<string-array name="language_data" translatable="false">
<item>eu</item>
<item>en</item>
<item>fi</item>
<item>de</item>
<item>ru</item>
<item>es</item>
</string-array>
</resources>

View file

@ -0,0 +1,6 @@
<resources>
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>
</resources>

View file

@ -0,0 +1,16 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreferenceCompat
app:key="dark_theme"
app:defaultValue="false"
app:iconSpaceReserved="false"
app:title="@string/switch_theme" />
<ListPreference
android:key="@string/language_preference"
android:title="@string/preference_title"
android:entries="@array/language_array"
android:entryValues="@array/language_data"
app:iconSpaceReserved="false" />
</PreferenceScreen>

View file

@ -0,0 +1,17 @@
package com.example.tuner
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}