Tutorial: Membuat Aplikasi Pengenal Chord Gitar Menggunakan Machine Learning

Pendahuluan

Halo, teman-teman! Pada kesempatan kali ini, kita akan belajar cara membuat aplikasi keren yang bisa mengenali chord gitar dari rekaman audio. Aplikasi ini akan menggunakan Flutter untuk front-end dan Flask untuk back-end, serta bantuan Machine Learning untuk mengenali chord gitar. Yuk, kita mulai!

Menyiapkan Dataset

Pertama-tama, kita perlu menyiapkan dataset yang akan digunakan untuk melatih model Machine Learning kita. Berikut adalah struktur direktori yang kita perlukan untuk dataset:

dataset/
├── A/
│   ├── audio1.wav
│   ├── audio2.wav
│   └── ...
├── Am/
│   ├── audio1.wav
│   ├── audio2.wav
│   └── ...
├── C/
│   ├── audio1.wav
│   ├── audio2.wav
│   └── ...
...

Setiap folder di dalam direktori dataset berisi file audio (.wav) dari chord yang sesuai dengan nama folder. Pastikan semua file audio tersimpan dengan benar di folder masing-masing chord.

 

Membuat Aplikasi Mobile dengan Flutter

Aplikasi mobile kita akan dibangun menggunakan Flutter. Aplikasi ini akan merekam audio dari pengguna saat mereka memainkan chord gitar, lalu mengirim file audio tersebut ke server untuk dianalisis.

Kode untuk Merekam Audio

Berikut adalah contoh kode untuk merekam audio menggunakan Flutter:


class ChordDetailPage extends StatefulWidget {
  const ChordDetailPage({Key? key}) : super(key: key);

  @override
  _ChordDetailPageState createState() => _ChordDetailPageState();
}

class _ChordDetailPageState extends State<ChordDetailPage> {
  final FlutterSoundRecorder _recorder = FlutterSoundRecorder();
  bool _isRecording = false;
  String _filePath = '';

  @override
  void initState() {
    super.initState();
    _requestPermissions();
    _openRecorder();
  }

  Future<void> _requestPermissions() async {
    var status = await Permission.microphone.status;
    if (!status.isGranted) {
      await Permission.microphone.request();
    }
    status = await Permission.storage.status;
    if (!status.isGranted) {
      await Permission.storage.request();
    }
  }

  Future<void> _openRecorder() async {
    await _recorder.openAudioSession();
  }

  void _startRecording() async {
    var tempDir = await getTemporaryDirectory();
    _filePath = '${tempDir.path}/temp.wav';
    await _recorder.startRecorder(toFile: _filePath);
    setState(() {
      _isRecording = true;
    });
  }

  void _stopRecording() async {
    await _recorder.stopRecorder();
    setState(() {
      _isRecording = false;
      _sendFile();
    });
  }

  void _sendFile() async {
    var uri = Uri.parse('$baseURL/upload');
    var request = http.MultipartRequest('POST', uri)
      ..files.add(await http.MultipartFile.fromPath('audio', _filePath));
    var response = await request.send();
    if (response.statusCode == 200) {
      var responseData = await http.Response.fromStream(response);
      var responseBody = json.decode(responseData.body);
      String recognizedChord = responseBody['recognized_chord'];
      if (recognizedChord != null) {
        _showAlert(context, recognizedChord == chordName ? 'Correct' : 'Wrong');
      }
    }
  }

  void _showAlert(BuildContext context, String title) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(title, textAlign: TextAlign.center),
          actions: <Widget>[
            TextButton(
              child: Text('Ok'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // Kode UI
    );
  }
}

Membuat Backend dengan Flask

Backend kita akan dibangun menggunakan Flask dan akan bertanggung jawab untuk memproses file audio yang dikirim oleh aplikasi mobile serta mengenali chord menggunakan model Machine Learning.

Kode untuk Ekstraksi Fitur Audio

Server kita akan menggunakan librosa untuk memproses file audio dan mengekstrak fitur chroma.


@app.route('/upload', methods=['POST'])
def upload_audio():
    if 'audio' not in request.files:
        return jsonify({'error': 'No audio file provided'}), 400

    audio_file = request.files['audio']
    file_path = os.path.join('C:\\temp', audio_file.filename)
    audio_file.save(file_path)

    y, sr = librosa.load(file_path)
    chroma = librosa.feature.chroma_stft(y=y, sr=sr)
    chroma_mean = np.mean(chroma, axis=1)
    recognized_chord = recognize_chord_svm(chroma_mean)

    os.remove(file_path)

    if recognized_chord:
        return jsonify({'recognized_chord': recognized_chord})

    return jsonify({'recognized_chord': None, 'error': 'Chord not recognized'})


Kode Model Machine Learning: Support Vector Machine (SVM)

Model SVM akan digunakan untuk mengenali chord dari fitur chroma yang diekstraksi dari file audio.


def load_svm_model():
    model_path = 'svm_model.pkl'
    if os.path.exists(model_path):
        return joblib.load(model_path)
    return None

svm_model = load_svm_model()

def recognize_chord_svm(chroma_mean):
    if svm_model:
        chord_label = svm_model.predict([chroma_mean])
        return chord_label[0]
    return None

Melatih Model Machine Learning

Selanjutnya, kita akan melatih model SVM menggunakan dataset yang sudah disiapkan. Berikut adalah langkah-langkah untuk melatih model:

Kode Pelatihan Model


import os
import numpy as np
from sklearn import svm
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
import joblib
import librosa

def extract_chroma_features(file_path):
    y, sr = librosa.load(file_path)
    chroma = librosa.feature.chroma_stft(y=y, sr=sr)
    chroma_mean = np.mean(chroma, axis=1)
    return chroma_mean

chords = ['C','A','Dm','Em','F','G','Am','D','E']

# Load dataset
X = []
y = []
dataset_dir = os.path.abspath('dataset')  # Path to your dataset
print(f"Dataset directory: {dataset_dir}")

for chord in chords:
    chord_dir = os.path.join(dataset_dir, chord)
    print(f"Checking directory: {chord_dir}")

    if not os.path.exists(chord_dir):
        print(f"Directory {chord_dir} does not exist. Please create it and add audio files.")
        continue

    files = [file_name for file_name in os.listdir(chord_dir) if file_name.endswith('.wav')]
    if len(files) == 0:
        print(f"No audio files found in directory {chord_dir}")
        continue
    print(f"Found {len(files)} files in directory {chord_dir}")

    for file_name in files:
        file_path = os.path.join(chord_dir, file_name)
        print(f"Processing file: {file_path}")

        if not os.path.exists(file_path):
            print(f"File {file_path} does not exist.")
            continue

        chroma_features = extract_chroma_features(file_path)
        X.append(chroma_features)
        y.append(chord)

# Convert to numpy arrays
X = np.array(X)
y = np.array(y)

# Check if we have more than one class
unique_classes = np.unique(y)
print(f"Unique classes found: {unique_classes}")

if len(unique_classes) <= 1:
    raise ValueError(f"The number of classes has to be greater than one; got {len(unique_classes)} class")

# Train SVM model
svm_model = make_pipeline(StandardScaler(), svm.SVC(kernel='linear'))
svm_model.fit(X, y)

# Save the trained model
joblib.dump(svm_model, 'svm_model.pkl')
print("Model has been trained and saved as svm_model.pkl")

Penjelasan Fungsi-Fungsi

  • extract_chroma_features(file_path): Fungsi ini menggunakan librosa untuk memuat file audio dan mengekstrak fitur chroma, kemudian menghitung rata-rata dari fitur chroma.
  • chords: Daftar chord yang akan dikenali oleh model.
  • X dan y: List yang menyimpan fitur chroma dan label chord yang sesuai.
  • dataset_dir: Path ke direktori dataset yang berisi folder-folder chord.
  • svm_model = make_pipeline(StandardScaler(), svm.SVC(kernel='linear')): Membuat pipeline yang terdiri dari scaler dan model SVM dengan kernel linear.
  • svm_model.fit(X, y): Melatih model SVM menggunakan dataset.
  • joblib.dump(svm_model, 'svm_model.pkl'): Menyimpan model yang telah dilatih ke dalam file svm_model.pkl.

Kesimpulan

Dengan mengikuti langkah-langkah dalam tutorial ini, kalian bisa membuat aplikasi yang mampu mengenali chord gitar dari rekaman audio. Aplikasi ini menggunakan kombinasi Flutter untuk front-end, Flask untuk back-end, dan model Machine Learning SVM yang telah dilatih dengan dataset yang sesuai. Selamat mencoba dan semoga berhasil!