

Picture this: a rainy Sunday afternoon, kids bouncing off the walls, and a parent desperately trying to find something educational yet fun. We pulled out the classic memory card game — flip two cards, find matching pairs.
The kids loved it. But something clicked in my head: What if instead of matching pictures, we matched sounds?
That question sparked MemoSonic.
Traditional memory games are purely visual. You see an image, remember its position, find its pair. Great for training visual memory, but what about:
We realized there was a gap. A big one.
| Traditional Memory | MemoSonic |
|---|---|
| Visual only | Sound-first approach |
| Static images | Interactive audio feedback |
| Limited accessibility | Inclusive by design |
| One learning style | Multiple categories for different interests |
We needed something that would:
Flutter was the obvious choice. Cross-platform, beautiful animations out of the box, and a fantastic ecosystem for audio libraries.
Here's something most developers don't think about: audio is hard.
Not the playback itself — that's straightforward. The hard part is:
We went through several iterations:
Version 1: Load all audio upfront
→ Problem: 3-second app startup, memory issues
Version 2: Stream audio on demand
→ Problem: Noticeable delay on first play
Version 3 (Final): Preload current category, lazy-load others
→ Sweet spot of performance and responsiveness
Here's where it gets nerdy (in the best way).
When we started MemoSonic, we had a problem: we needed hundreds of audio files. 168 chord sounds. 14 scale recordings. 8 rhythm patterns. Individual notes. Where do you even get that?
Answer: You generate them programmatically.

Instead of recording a pianist playing every chord (expensive, time-consuming), we wrote Python scripts that:
# Chord intervals (semitones from root)
CHORD_TYPES = {
"maj": [0, 4, 7], # Major: root, major 3rd, perfect 5th
"min": [0, 3, 7], # Minor: root, minor 3rd, perfect 5th
"7": [0, 4, 7, 10], # Dominant 7th
"m7": [0, 3, 7, 10], # Minor 7th
"maj7": [0, 4, 7, 11], # Major 7th
"aug": [0, 4, 8], # Augmented
"dim": [0, 3, 6], # Diminished
}
12 root notes × 7 chord types = 84 chords. Add enharmonic equivalents (C# = Db, etc.) and we hit 168 unique chord files.
The pipeline:
MIDI generation (midiutil)
↓
FluidSynth + Salamander Piano SF2
↓
WAV file
↓
FFmpeg MP3 encoding
↓
Final audio asset
The rhythm category was even more interesting. We didn't use samples at all — we synthesized every drum sound mathematically.
def generate_kick(duration_ms=150):
"""Generate a punchy kick drum sound"""
for i in range(num_samples):
t = i / SAMPLE_RATE
# Pitch envelope: starts high, drops quickly
freq = freq_end + (freq_start - freq_end) * math.exp(-decay_rate * t)
# Main tone with pitch drop
tone = math.sin(2 * math.pi * freq * t)
# Add click transient at the start
if t < 0.005:
click = (1 - t / 0.005) * 0.5
...
Kick drum — A sine wave that rapidly drops in pitch (150Hz → 50Hz) with a click transient.
Snare drum — Shell resonance (170Hz with harmonics) + attack transient (450Hz) + filtered noise for the snare wires. Plus a touch of room reverb.
Hi-hat — White noise mixed with metallic high-frequency tones (6kHz, 8kHz, 10kHz), shaped with ADSR envelopes.
Then we programmed the actual rhythm patterns:
RHYTHMS = [
("4_4", "4/4 Time", "4/4", 100, [
(0, "kick", 0), # Beat 1
(1, "snare", -2), # Beat 2
(2, "kick", -2), # Beat 3
(3, "snare", -2), # Beat 4
# Off-beat hi-hats
(0.5, "hihat", -6),
(1.5, "hihat", -6),
...
]),
("swing", "Swing", "4/4", 120, [
# Triplet-based timing for swing feel
(0.66, "hihat", -6), # Swung eighth
...
]),
]
8 rhythm patterns, each with its own BPM, time signature, and accent patterns.
For the Notes category, we used pydub's sine wave generator:
NOTES = [
("c", "C", 261.63), # C4 (Middle C)
("d", "D", 293.66), # D4
("e", "E", 329.63), # E4
...
("c_octave", "C (Octave)", 523.25), # C5
]
def generate_note_audio(frequency, duration_ms):
tone = Sine(frequency).to_audio_segment(duration=duration_ms)
tone = tone.fade_in(50).fade_out(200) # Avoid clicks
return tone
Simple, clean, and perfect for ear training.
Raw generated audio isn't always game-ready. We wrote additional scripts:
Cut scales to ascending only — Original scales went up AND down. Too long. We cut them to just the ascending portion:
def cut_to_ascending(file_path):
audio = AudioSegment.from_mp3(file_path)
half_point = len(audio) // 2
ascending_only = audio[:half_point]
ascending_only.export(file_path, format="mp3")
Trim chord arpeggios — Some chords had unwanted arpeggio intros. FFmpeg to the rescue:
ffmpeg -y -i chord.mp3 -ss [start_time] -acodec libmp3lame chord_trimmed.mp3
Batch update SVG colors — Our chord diagrams needed color adjustments to match the app theme. Regex-based batch processing:
COLOR_REPLACEMENTS = {
'#f3f8f3': '#000000', # Inactive keys: light → dark
'#b3cc57': '#C6F222', # Active keys: old green → MTL lime
}
By the end, our content pipeline generated:
| Category | Files | Method |
|---|---|---|
| Chords | 168 audio + 168 SVG | MIDI → FluidSynth → FFmpeg |
| Scales | 14 audio + 14 SVG | MIDI → FluidSynth → FFmpeg |
| Notes | 8 audio + 8 SVG | pydub sine wave synthesis |
| Rhythms | 8 audio + 8 PNG | Mathematical drum synthesis |
| Animals | 18 audio + 18 PNG | Curated library |
| Instruments | 8 audio + 8 PNG | Curated samples |
Total: 300+ assets, mostly generated programmatically.
Could we have licensed a chord library? Sure. But:
Plus, writing a drum synthesizer from scratch is just fun.
While we started with music education in mind, we quickly realized the concept works for much more.

Chords — Can you tell the difference between a major and minor chord? What about diminished vs. augmented? This category trains your ear to recognize the emotional quality of different chord types.
Scales — From the bright C Major to the melancholic A Natural Minor, players learn to identify scales by their unique character.
Notes — Perfect for beginners learning to identify individual pitches on the musical staff.
Rhythms — 3/4 waltz? 4/4 rock beat? Syncopated funk? Train your rhythmic ear.
Animals — 18 animal sounds, from the roar of a lion to the chirp of a bird. Perfect for younger kids or anyone who just wants a fun challenge.
Instruments — Can you distinguish a trumpet from a saxophone? A violin from a cello? Harder than you'd think!
Not everyone learns the same way. That's why MemoSonic offers two distinct game modes:
This is the heart of the app. Tap a card, hear a sound. Remember that sound. Find its match.
1. Tap card → Hear sound (no visual)
2. Tap another card → Hear second sound
3. Match? → Cards reveal and stay
4. No match? → Cards flip back, remember the sounds!
For those who want a traditional experience, or as a comparison to understand how much harder audio matching is!
1. Tap card → Image briefly appears (1 second)
2. Tap another card → Second image appears
3. Match? → Cards stay revealed
4. No match? → Images hide, remember positions!
We designed three difficulty levels, each carefully balanced:
| Level | Cards | Pairs | Estimated Time |
|---|---|---|---|
| Easy | 6 | 3 | 2-3 minutes |
| Normal | 12 | 6 | 5-7 minutes |
| Hard | 20 | 10 | 10-15 minutes |
The jump from 6 to 12 cards isn't just "twice as hard" — it's exponentially more challenging. Your brain can hold about 7 items in working memory. At 12 cards, you're constantly pushing that limit.
At 20 cards? It's a real workout.
Here's where it gets important.
Traditional memory games are impossible for blind or visually impaired players. The entire mechanic relies on seeing and remembering visual positions.
MemoSonic flips this on its head.
In Memosonic mode, vision is secondary. You're listening, remembering sounds, matching audio. A visually impaired player can:
We made several deliberate choices:
High Contrast UI
Large Touch Targets
Audio Feedback
Simple Navigation
lib/
├── main.dart # Entry point, splash screen
├── core/
│ ├── routes.dart # GoRouter navigation
│ ├── theme.dart # Material 3 dark theme
│ └── game_utils.dart # Category definitions, game data
├── features/
│ ├── home_screen.dart # Category selection grid
│ ├── level_screen.dart # Difficulty picker
│ ├── game_screen.dart # Main gameplay
│ └── settings_screen.dart # Settings hub
└── widgets/
└── app_logo.dart # Reusable logo component
dependencies:
flutter_riverpod: ^3.0.1 # State management
go_router: ^16.3.0 # Navigation
just_audio: ^0.10.5 # Primary audio engine
audioplayers: ^6.1.0 # Alternative audio playback
flutter_svg: ^2.0.10 # SVG rendering for diagrams
shared_preferences: ^2.5.3 # Local settings storage
One of the most satisfying parts of the app is the card flip animation. Here's the approach:
// Simplified card flip logic
AnimatedBuilder(
animation: _flipAnimation,
builder: (context, child) {
final angle = _flipAnimation.value * pi;
final isFront = angle < pi / 2;
return Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.001) // Perspective
..rotateY(angle),
alignment: Alignment.center,
child: isFront ? _buildFrontFace() : _buildBackFace(),
);
},
)
The trick is the perspective transform (setEntry(3, 2, 0.001)) — it gives that satisfying 3D effect without being distracting.
In a sound-based game, even tiny delays feel wrong. We spent weeks optimizing audio playback to ensure instant response.
Our first playtest with actual children revealed:
Building for accessibility from day one is 10x easier than retrofitting. The decisions we made early (audio-first gameplay, high contrast, large targets) paid off.
Our first design had:
We cut all of it. The core experience — match sounds, train your ear — didn't need any of that. It needed to work flawlessly.
We have a bunch of ideas brewing for the next iteration. But here's the thing — we'd rather build what you actually want.
Take a look at what we're considering:
More Categories
Enhanced Accessibility
Multiplayer Mode
Something else entirely?
Maybe you're a music teacher who needs specific intervals training. Maybe you work with visually impaired students and have insights we haven't considered. Maybe your kid is obsessed with dinosaurs and you want dinosaur sounds.
We're listening.
Drop us a line at support@musictechlab.io and tell us:
The best features come from real users with real needs. Don't be shy — your idea might end up in the next update.
Here's an idea that won't leave our heads...
What if MemoSonic wasn't just an app, but a physical toy you could hold in your hands?
Picture a compact device with a grid of large, tactile buttons. Each button:
An 8×8 matrix would give us 64 buttons — enough for complex games while keeping each button big enough to press comfortably:
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
[🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘] [🔘]
Easy mode? Use a 3×2 section. Hard mode? The whole grid lights up.
Screen-free play. Parents increasingly want toys that don't involve staring at a screen. A physical MemoSonic would sit on the kitchen table, travel in a backpack, work without WiFi.
True tactile accessibility. For visually impaired users, physical buttons in fixed positions are far easier to navigate than a touchscreen. You can feel your way around. Build muscle memory. No screen reader required.
Multiplayer without devices. Gather around the table. Take turns. Compete. No "pass the phone" awkwardness.
Durability. Kids are rough. A well-designed hardware toy can survive drops, spills, and sibling conflicts.
If we were to build this, we'd probably explore:
The app and hardware could even sync — unlock new sounds on the device by mastering them in the app first.
This is where it gets really exciting.
For a blind child, a touchscreen memory game is possible but challenging. A physical device with buttons in consistent positions? That's a game they can master as well as any sighted player. Maybe better — they've been training their auditory memory their whole life.
We imagine:
Right now, this is just an idea — a dream sketched on whiteboards and discussed over coffee. We haven't built a prototype yet. We're not sure if we will.
But we could, if there's real interest.
Would you buy a physical MemoSonic for your kids? For a classroom? For a visually impaired family member? Would you back it on Kickstarter?
Let us know. If enough people say "yes, build this thing!" — we just might.
📧 support@musictechlab.io — subject line: "Hardware MemoSonic"
If the response is strong enough, we'll start prototyping and document the entire journey. Stay tuned.
MemoSonic is available now:
Whether you're a music teacher looking for ear training tools, a parent wanting educational screen time, or someone who just wants to see if they can beat their kids at a memory game — give it a try.
MemoSonic started as a rainy day experiment. It became something more — a proof that:
Sometimes the best projects come from playing with your kids.
We thought it might be useful to share some honest insights from building MemoSonic — especially if you're considering commissioning a mobile app yourself.
MemoSonic from idea to production: ~10 calendar months, but effectively 2-3 weeks of intense work.
Why the difference? Because projects have their own rhythm — there are pauses for testing ideas, gathering feedback, handling other priorities. Realistically:
| Phase | Time |
|---|---|
| Prototype / proof of concept | 1-2 days |
| Core functionality | 3-5 days |
| UI/UX polish | 3-5 days |
| Testing, bugs, deployment | 2-5 days |
| Effective total | 2-3 weeks |
1. Audio/Media — Sounds simple ("just play a sound"), but:
2. iOS Builds — Every mobile project confirms this. Certificates, provisioning profiles, App Store review. Android is simpler.
3. Content and Copyright — Want to use a famous melody? Images from the internet? You either generate your own assets or buy licenses. (We had to remove Metallica from the project for this reason.)
MemoSonic is "just" a memory game with sounds. Sounds like a weekend project, right?
And yet:
What seems like a "simple app" often requires:
MVP in 5 days, polishing — endless.
The first working version comes together quickly. But the difference between "it works" and "it works well on every device, looks professional, and doesn't crash" — that's weeks of additional work.
If you're planning to build an app, budget for:
The silver lining? Cross-platform frameworks like Flutter mean you get both iOS and Android from a single codebase. One team, one codebase, two app stores. That's a massive time and cost saver compared to building native apps separately.
The good news? With the right team and realistic expectations, even ambitious ideas can become polished products. MemoSonic started as a rainy Sunday vibe-coded game with kids. Now it's a people train their ears.
Have questions about MemoSonic or want to share your experience?
Reach out to us — we'd love to hear from you.
Assembly Instructions App - Galeco Mobile App
How we developed a mobile application for Galeco to help roofers, architects, and contractors with assembly instructions. A case study on building an offline-capable React Native app with 3D video instructions for the construction industry.
Loyalty Program Application - Custom Software Development for Marketing & Communication Platform
How we developed a loyalty program application for Forum shopping mall to issue prepaid gift cards based on purchase amounts. A case study on building a tablet-based application with backend API and frontend panel for promotional campaigns.