VoiceChanger — Flutter + Dart FFI + C++ SoLoud DSP Engine
Flutter voice changer yang mengintegrasikan C++ SoLoud audio engine via Dart FFI (bukan MethodChannel) untuk manipulasi pitch dan tempo zero-latency, dengan Clean Architecture dan Dart Isolate untuk visualizer.
- Role
- Solo Flutter developer (eksplorasi teknologi)
- Ownership
- Solo builder: integrasi Dart FFI ke C++ SoLoud, Clean Architecture, BLoC/Cubit, Dart Isolate untuk visualizer, dan dokumentasi DSP engine architecture.
- Team
- Solo project
- Period
- 2026
- Focus
- Flutter, Flutter Developer, Mobile Developer
Overview
VoiceChanger adalah project eksplorasi Flutter yang membuktikan bahwa UI cross-platform Dart bisa melakukan direct memory manipulation ke biner C++ native untuk mencapai pemrosesan sinyal digital (DSP) sekelas aplikasi native, tanpa overhead asynchronous MethodChannel. Pengguna merekam suara, memilih template preset (Normal, Chipmunk, Monster), dan slider pitch/tempo langsung mengubah parameter di memory C++ secara synchronous.
Tech & Libraries
Teknologi dan library yang dipakai atau disentuh di project ini:
Problem
Manipulasi audio real-time di Flutter biasanya memakai MethodChannel yang bersifat asynchronous dan melewati OS message queue. Untuk DSP, delay 15 milidetik saja sudah merusak pengalaman karena suara terasa lag saat slider digeser. Selain itu, visualizer gelombang suara yang berjalan di Main Thread akan menyebabkan frame drop karena beban kalkulasi animasi bersaing dengan rendering UI.
My Role & Ownership
Solo builder: integrasi Dart FFI ke C++ SoLoud, Clean Architecture, BLoC/Cubit, Dart Isolate untuk visualizer, dan dokumentasi DSP engine architecture.
Technical Approach
Mengintegrasikan flutter_soloud yang membungkus C++ SoLoud engine via Dart FFI. Saat slider pitch digeser, Dart langsung menimpa pointer float di memory C++ secara synchronous, melewati OS queue sepenuhnya. SoLoud membaca perubahan di Audio Thread terpisah dan mengubah nada secara instan.
Visualizer gelombang suara dijalankan di Dart Isolate terpisah agar Main Thread tidak drop di bawah 60fps. Clean Architecture diterapkan dengan tiga lapisan: Data (AudioNativeDataSource memanggil flutter_soloud, file picker, dan history), Domain (AudioFilterEntity, UseCases, Repository contract), dan Presentation (VoiceTunerCubit dan AuraVoiceCubit via BLoC/Cubit).
Architecture Notes
Tiga lapisan Clean Architecture: Data (AudioNativeDataSource memanggil flutter_soloud, file_picker, dan local directory), Domain (AudioFilterEntity, IAudioRepository, tiga UseCase), dan Presentation (VoiceTunerCubit untuk slider state, AuraVoiceCubit untuk playback state). Cubit tidak tahu tentang dart:io atau file_picker secara langsung; mereka hanya memanggil UseCase yang di-inject via GetIt.
Saat runtime, Dart dan C++ hidup di dua ruang memory berbeda dalam satu binary: Dart memakai Garbage Collector, C++ memakai manual malloc/free. FFI menjadi jembatan synchronous yang memungkinkan Dart menulis langsung ke pointer C++ tanpa melewati OS queue.
Trade-offs
Memilih Dart FFI alih-alih MethodChannel untuk audio karena MethodChannel asynchronous dan melewati OS message queue, yang menambah latency tidak terduga untuk kasus DSP real-time. Konsekuensinya setup FFI lebih kompleks dan butuh pemahaman pointer management.
Export audio ke file baru (re-encoding) ditunda ke v2 karena membutuhkan ffmpeg_kit_flutter yang menambah kompleksitas build iOS; MVP fokus pada demonstrasi DSP pipeline dulu. Live monitoring (efek real-time saat merekam) juga ditunda karena routing audio dua arah rentan feedback loop di hardware Android yang terfragmentasi.
Implementation Highlights
- Dart FFI dipakai alih-alih MethodChannel: Dart langsung menimpa pointer float di memory C++ secara synchronous, mengeliminasi overhead OS message queue.
- SoLoud DSP pipeline: file audio di-decode ke PCM buffer C++, lalu pitch shifting (resampling + time-stretch) dan reverb (convolution) dijalankan on-the-fly sebelum dikirim ke OS Audio API (CoreAudio/OpenSL ES).
- Dart Isolate untuk fake visualizer: kalkulasi animasi gelombang suara dijalankan di thread terpisah agar Main Thread tidak drop frame.
- Clean Architecture: AudioNativeDataSource sebagai satu-satunya titik kontak ke flutter_soloud dan file system, UseCase sebagai orkestrator per aksi (apply filter, get history, pick file), Cubit sebagai state manager di Presentation.
- Satu binary tunggal: C++ SoLoud dikompilasi via CMake (Android) dan CocoaPods/Clang (iOS) menjadi shared library yang di-link ke Flutter engine, bukan server terpisah.
Results
- Menunjukkan pemahaman batas antara Dart runtime dan C++ native memory, cara kerja Dart FFI sebagai alternatif MethodChannel untuk kasus latency-sensitive, dan bagaimana Dart Isolate dipakai untuk memindahkan beban komputasi dari Main Thread.
- Manipulasi pitch dan tempo real-time via Dart FFI ke C++ SoLoud engine tanpa latency yang terasa.
- Template preset (Normal, Chipmunk, Monster) mengubah parameter DSP secara instan saat dipilih.
- Dart Isolate untuk fake visualizer animasi agar Main Thread tetap smooth di 60fps.
- Clean Architecture tiga lapisan dengan UseCase untuk record, import file, dan history.
- Redesign plan Cupertino light mode terdokumentasi untuk iterasi UI berikutnya.
- DSP pipeline: decode PCM → pitch shift (resampling + time-stretch) → reverb (convolution) → OS Audio API → speaker.
- Public proof: repo publik di GitHub dengan dokumentasi DSP_ENGINE_ARCHITECTURE.md.