| 1 |
|
| 2 |
|
| 3 |
use mt_core::types::CommunityRole; |
| 4 |
use sqlx::PgPool; |
| 5 |
use uuid::Uuid; |
| 6 |
|
| 7 |
pub async fn run(pool: &PgPool) { |
| 8 |
|
| 9 |
let thread_count: i64 = |
| 10 |
sqlx::query_scalar("SELECT COUNT(*) FROM threads") |
| 11 |
.fetch_one(pool) |
| 12 |
.await |
| 13 |
.unwrap_or(0); |
| 14 |
if thread_count > 0 { |
| 15 |
tracing::info!("seed data already exists, skipping"); |
| 16 |
return; |
| 17 |
} |
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
let users = seed_users(pool).await; |
| 22 |
|
| 23 |
|
| 24 |
|
| 25 |
let rust_id = seed_community( |
| 26 |
pool, |
| 27 |
"Rust Programming", |
| 28 |
"rust", |
| 29 |
Some("All things Rust — language, ecosystem, tooling."), |
| 30 |
) |
| 31 |
.await; |
| 32 |
|
| 33 |
let music_id = seed_community( |
| 34 |
pool, |
| 35 |
"Music Production", |
| 36 |
"music", |
| 37 |
Some("DAWs, plugins, mixing, mastering, sound design."), |
| 38 |
) |
| 39 |
.await; |
| 40 |
|
| 41 |
let selfhosted_id = seed_community( |
| 42 |
pool, |
| 43 |
"Self-Hosted", |
| 44 |
"selfhosted", |
| 45 |
Some("Running your own infrastructure. No cloud required."), |
| 46 |
) |
| 47 |
.await; |
| 48 |
|
| 49 |
|
| 50 |
|
| 51 |
|
| 52 |
let rust_general = seed_category(pool, rust_id, "General", "general", 0, Some("Anything that doesn't fit elsewhere.")).await; |
| 53 |
let rust_help = seed_category(pool, rust_id, "Help & Questions", "help", 1, Some("Ask for help, get answers.")).await; |
| 54 |
let _rust_show = seed_category(pool, rust_id, "Show & Tell", "show", 2, Some("Share what you've built.")).await; |
| 55 |
let _rust_meta = seed_category(pool, rust_id, "Meta", "meta", 3, Some("Discussion about this community itself.")).await; |
| 56 |
|
| 57 |
|
| 58 |
let music_general = seed_category(pool, music_id, "General", "general", 0, Some("General music production discussion.")).await; |
| 59 |
let music_mixing = seed_category(pool, music_id, "Mixing & Mastering", "mixing", 1, Some("Techniques for getting a polished mix.")).await; |
| 60 |
let music_sound = seed_category(pool, music_id, "Sound Design", "sound-design", 2, Some("Synthesis, sampling, and sound creation.")).await; |
| 61 |
|
| 62 |
|
| 63 |
let sh_general = seed_category(pool, selfhosted_id, "General", "general", 0, Some("General self-hosting discussion.")).await; |
| 64 |
let _sh_homelab = seed_category(pool, selfhosted_id, "Homelab", "homelab", 1, Some("Hardware, networking, and home server setups.")).await; |
| 65 |
|
| 66 |
|
| 67 |
|
| 68 |
for user in &users { |
| 69 |
seed_membership(pool, user.id, music_id, CommunityRole::Member).await; |
| 70 |
} |
| 71 |
|
| 72 |
seed_membership_upsert(pool, users[0].id, rust_id, CommunityRole::Owner).await; |
| 73 |
seed_membership_upsert(pool, users[0].id, music_id, CommunityRole::Owner).await; |
| 74 |
seed_membership_upsert(pool, users[0].id, selfhosted_id, CommunityRole::Owner).await; |
| 75 |
seed_membership_upsert(pool, users[1].id, rust_id, CommunityRole::Member).await; |
| 76 |
seed_membership_upsert(pool, users[1].id, music_id, CommunityRole::Moderator).await; |
| 77 |
|
| 78 |
|
| 79 |
|
| 80 |
let welcome_id = seed_thread(pool, rust_general, users[0].id, "Welcome — read before posting", true, false).await; |
| 81 |
seed_post(pool, welcome_id, users[0].id, "Welcome to the Rust Programming community. Please be respectful, stay on topic, and use code blocks for code snippets.").await; |
| 82 |
|
| 83 |
let async_id = seed_thread(pool, rust_general, users[1].id, "How do I get started with async Rust?", false, false).await; |
| 84 |
seed_post(pool, async_id, users[1].id, "I've been writing synchronous Rust for a few months and want to start using async/await. What runtime should I pick? Is tokio the only option?\n\nAny recommended tutorials or blog posts would be great.").await; |
| 85 |
seed_post(pool, async_id, users[0].id, "Tokio is the most popular and what most web frameworks (Axum, Actix) use. There's also `async-std` and `smol`, but the ecosystem gravitates toward tokio.\n\nStart with the tokio tutorial: it covers spawning tasks, channels, and I/O.").await; |
| 86 |
|
| 87 |
let error_id = seed_thread(pool, rust_help, users[1].id, "Best practices for error handling in Axum", false, false).await; |
| 88 |
seed_post(pool, error_id, users[1].id, "What's the recommended way to handle errors in Axum handlers? Should I use `anyhow`, `thiserror`, or something else? I keep writing `.map_err(|e| ...)` everywhere.").await; |
| 89 |
|
| 90 |
|
| 91 |
|
| 92 |
let caddy_id = seed_thread(pool, sh_general, users[0].id, "Caddy vs nginx for reverse proxy", false, false).await; |
| 93 |
seed_post(pool, caddy_id, users[0].id, "I have been using nginx for years but Caddy's automatic HTTPS is tempting. Anyone made the switch? What are the tradeoffs?").await; |
| 94 |
seed_post(pool, caddy_id, users[3].id, "Switched last year. Caddy's config is so much simpler. Automatic cert renewal is great. Only downside is slightly higher memory usage but it is negligible for small setups.").await; |
| 95 |
|
| 96 |
|
| 97 |
|
| 98 |
seed_music_general(pool, music_general, &users).await; |
| 99 |
seed_music_mixing(pool, music_mixing, &users).await; |
| 100 |
seed_music_sound_design(pool, music_sound, &users).await; |
| 101 |
|
| 102 |
let total_threads: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM threads") |
| 103 |
.fetch_one(pool) |
| 104 |
.await |
| 105 |
.unwrap_or(0); |
| 106 |
let total_posts: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM posts") |
| 107 |
.fetch_one(pool) |
| 108 |
.await |
| 109 |
.unwrap_or(0); |
| 110 |
|
| 111 |
tracing::info!( |
| 112 |
"seeded 3 communities, {} users, {} threads, {} posts", |
| 113 |
users.len(), |
| 114 |
total_threads, |
| 115 |
total_posts |
| 116 |
); |
| 117 |
} |
| 118 |
|
| 119 |
struct SeedUser { |
| 120 |
id: Uuid, |
| 121 |
} |
| 122 |
|
| 123 |
async fn seed_users(pool: &PgPool) -> Vec<SeedUser> { |
| 124 |
let user_data = [ |
| 125 |
("00000000-0000-0000-0000-000000000001", "admin", "Admin"), |
| 126 |
("00000000-0000-0000-0000-000000000002", "maxmj", "Max"), |
| 127 |
("00000000-0000-0000-0000-000000000003", "synthwave99", "Juno"), |
| 128 |
("00000000-0000-0000-0000-000000000004", "basshunter", "Erik"), |
| 129 |
("00000000-0000-0000-0000-000000000005", "tape_hiss", "Rae"), |
| 130 |
("00000000-0000-0000-0000-000000000006", "drumroom", "Cole"), |
| 131 |
("00000000-0000-0000-0000-000000000007", "patchwork", "Lina"), |
| 132 |
("00000000-0000-0000-0000-000000000008", "detuned", "Kai"), |
| 133 |
("00000000-0000-0000-0000-000000000009", "resampled", "Noor"), |
| 134 |
("00000000-0000-0000-0000-00000000000a", "clipgain", "Wren"), |
| 135 |
]; |
| 136 |
|
| 137 |
let mut users = Vec::new(); |
| 138 |
for (uuid_str, username, display_name) in &user_data { |
| 139 |
let id = Uuid::parse_str(uuid_str).unwrap(); |
| 140 |
sqlx::query( |
| 141 |
"INSERT INTO users (mnw_account_id, username, display_name) |
| 142 |
VALUES ($1, $2, $3) |
| 143 |
ON CONFLICT (mnw_account_id) DO NOTHING", |
| 144 |
) |
| 145 |
.bind(id) |
| 146 |
.bind(username) |
| 147 |
.bind(display_name) |
| 148 |
.execute(pool) |
| 149 |
.await |
| 150 |
.expect("failed to seed user"); |
| 151 |
users.push(SeedUser { id }); |
| 152 |
} |
| 153 |
users |
| 154 |
} |
| 155 |
|
| 156 |
|
| 157 |
async fn seed_music_general(pool: &PgPool, category_id: Uuid, users: &[SeedUser]) { |
| 158 |
let threads: &[(&str, &str, &[&str])] = &[ |
| 159 |
( |
| 160 |
"Welcome to Music Production", |
| 161 |
"Ground rules: be kind, share knowledge, no self-promo spam. Use the right category for your topic.", |
| 162 |
&["Glad to be here.", "Thanks for setting this up."], |
| 163 |
), |
| 164 |
( |
| 165 |
"What DAW are you using in 2026?", |
| 166 |
"Curious what everyone is running these days. I have been on Ableton for years but keep hearing about Bitwig.", |
| 167 |
&[ |
| 168 |
"Reaper. Lightweight, cheap, endlessly customizable.", |
| 169 |
"Bitwig since version 4. The modulation system is unmatched.", |
| 170 |
"FL Studio. Started on it when I was 14, never left.", |
| 171 |
"Ableton but I keep a Reaper install for editing and batch processing.", |
| 172 |
"Logic. It just works and the stock plugins are surprisingly good.", |
| 173 |
], |
| 174 |
), |
| 175 |
( |
| 176 |
"Favorite free plugins?", |
| 177 |
"What are your go-to free VSTs? Looking for synths, effects, anything.", |
| 178 |
&[ |
| 179 |
"Vital is the obvious answer. Best free synth by a mile.", |
| 180 |
"Valhalla Supermassive for reverb/delay. Sounds incredible for free.", |
| 181 |
"TDR Nova for EQ. Clean, surgical, zero CPU.", |
| 182 |
"Dexed if you want FM synthesis. Basically a free DX7.", |
| 183 |
], |
| 184 |
), |
| 185 |
( |
| 186 |
"How do you organize your sample library?", |
| 187 |
"My sample folder is a disaster. Thousands of files with no structure. How do you keep things findable?", |
| 188 |
&[ |
| 189 |
"Genre > Type > Character. So like Electronic > Kicks > Punchy. Took a weekend to sort but worth it.", |
| 190 |
"I use tags instead of folders. AudioFiles has been great for this actually.", |
| 191 |
"Honestly I just search. If the filename is descriptive enough, search wins over folders every time.", |
| 192 |
], |
| 193 |
), |
| 194 |
( |
| 195 |
"Analog vs digital debate in 2026", |
| 196 |
"Is there still a meaningful difference? Modern plugins are so good that I genuinely cannot tell in blind tests anymore.", |
| 197 |
&[ |
| 198 |
"The difference is workflow, not sound. Hardware forces commitment.", |
| 199 |
"I sold all my hardware last year. Zero regrets. Plugins are there.", |
| 200 |
"The tactile experience matters. Turning a real knob is different from clicking a virtual one.", |
| 201 |
"Both. I track through analog preamps and process in the box.", |
| 202 |
], |
| 203 |
), |
| 204 |
( |
| 205 |
"How long did it take you to finish your first track?", |
| 206 |
"Been producing for 3 months and I cannot seem to finish anything. Is this normal?", |
| 207 |
&[ |
| 208 |
"Totally normal. Took me a year to finish something I was not embarrassed by.", |
| 209 |
"Force yourself to finish bad tracks. The skill of finishing is separate from the skill of producing.", |
| 210 |
"Set a deadline. 48 hours from start to bounce. Quality does not matter, completion does.", |
| 211 |
"Still working on my first one honestly.", |
| 212 |
"About 6 months. And it was terrible. But I finished it and that mattered.", |
| 213 |
], |
| 214 |
), |
| 215 |
( |
| 216 |
"Studio monitors vs headphones for mixing?", |
| 217 |
"I live in an apartment and cannot treat the room properly. Should I just mix on headphones?", |
| 218 |
&[ |
| 219 |
"Headphones are fine if you know their character. Use a reference plugin like Sonarworks.", |
| 220 |
"I mix on DT 770s and reference on my car stereo. Not ideal but it works.", |
| 221 |
"Even cheap acoustic treatment helps. Hang some moving blankets.", |
| 222 |
], |
| 223 |
), |
| 224 |
( |
| 225 |
"What's your creative process?", |
| 226 |
"Do you start with drums, melody, a sample? Curious how other people approach a blank session.", |
| 227 |
&[ |
| 228 |
"Always start with chords. Everything else follows from the harmony.", |
| 229 |
"I jam on a synth until something clicks, then build around that loop.", |
| 230 |
"Sound design first. Find an interesting texture, then write something that serves it.", |
| 231 |
"Drums. Always drums. Get the groove right and the rest writes itself.", |
| 232 |
"I hum melodies into my phone all day, then sit down and try to recreate them.", |
| 233 |
"Start with a reference track. Analyze the arrangement, then write something inspired by the structure.", |
| 234 |
], |
| 235 |
), |
| 236 |
( |
| 237 |
"Best MIDI controllers under $200?", |
| 238 |
"Looking for something with keys and some knobs. Not a full workstation, just something to play ideas into the DAW.", |
| 239 |
&[ |
| 240 |
"Arturia Keystep 37. Great keybed for the price, plus the arpeggiator and sequencer.", |
| 241 |
"Novation Launchkey MK3. Deep DAW integration if you use Ableton.", |
| 242 |
"Akai MPK Mini. Tiny but surprisingly capable.", |
| 243 |
], |
| 244 |
), |
| 245 |
( |
| 246 |
"CPU overload — how do you deal with it?", |
| 247 |
"My sessions keep hitting 100% CPU. Running a Ryzen 5 3600 with 16GB RAM. Is it time to upgrade or am I doing something wrong?", |
| 248 |
&[ |
| 249 |
"Freeze tracks you are not actively working on. Most DAWs support this.", |
| 250 |
"Bounce MIDI to audio once you are happy with the sound. Frees up the plugin.", |
| 251 |
"Check your buffer size. 256 for recording, 1024+ for mixing.", |
| 252 |
"Your CPU is fine. It is probably one plugin eating everything. Check per-plugin CPU.", |
| 253 |
], |
| 254 |
), |
| 255 |
( |
| 256 |
"Music theory: how much do you actually use?", |
| 257 |
"I know basic chords and scales but never studied theory formally. How much do you all actually apply?", |
| 258 |
&[ |
| 259 |
"Enough to communicate with other musicians. Circle of fifths, chord functions, basic voice leading.", |
| 260 |
"Almost none. I go by ear and fix what sounds wrong.", |
| 261 |
"A lot. Understanding why something sounds good helps you recreate it faster.", |
| 262 |
], |
| 263 |
), |
| 264 |
( |
| 265 |
"Side-chaining techniques", |
| 266 |
"What is your preferred method for side-chaining? Compressor? Volume automation? LFO tool?", |
| 267 |
&[ |
| 268 |
"Trackspacer. Not technically side-chain compression but solves the same problem better.", |
| 269 |
"Volume shaper plugin. More precise than a compressor and you can draw the exact curve.", |
| 270 |
"Classic compressor side-chain. Simple, works, everyone knows how to do it.", |
| 271 |
"I automate the volume manually. Full control, no artifacts.", |
| 272 |
], |
| 273 |
), |
| 274 |
( |
| 275 |
"How do you avoid ear fatigue?", |
| 276 |
"I can mix for maybe 2 hours before everything starts sounding the same. Any tips?", |
| 277 |
&[ |
| 278 |
"Take breaks every 45 minutes. Walk around, drink water, reset.", |
| 279 |
"Mix at low volume. If it sounds good quiet, it will sound good loud.", |
| 280 |
"Reference constantly. Switch to a commercial track every 15 minutes.", |
| 281 |
], |
| 282 |
), |
| 283 |
( |
| 284 |
"Collaboration: how do you share projects?", |
| 285 |
"Want to collaborate with a friend who uses a different DAW. What is the best approach?", |
| 286 |
&[ |
| 287 |
"Stems. Bounce each track as a WAV, share via cloud storage.", |
| 288 |
"MIDI + stems for the parts that need to be editable.", |
| 289 |
"We just use the same DAW. Easier than any workaround.", |
| 290 |
], |
| 291 |
), |
| 292 |
( |
| 293 |
"Loudness standards for streaming platforms", |
| 294 |
"Spotify targets -14 LUFS, Apple Music -16. Should I master to a specific target or just make it sound good?", |
| 295 |
&[ |
| 296 |
"Master to what sounds best, then check loudness after. Most platforms normalize anyway.", |
| 297 |
"I aim for -12 to -14. Leaves headroom but still competitive.", |
| 298 |
"The number matters less than the dynamic range. A dynamic -14 sounds better than a squashed -8.", |
| 299 |
], |
| 300 |
), |
| 301 |
( |
| 302 |
"What headphones do you use?", |
| 303 |
"Looking for mixing headphones. Budget around $150-300.", |
| 304 |
&[ |
| 305 |
"Sennheiser HD 600. Flat, detailed, comfortable for long sessions.", |
| 306 |
"Beyerdynamic DT 990 Pro. Wide soundstage. A bit bright but you learn the character.", |
| 307 |
"AKG K712. Open-back, great imaging.", |
| 308 |
"Audio-Technica ATH-M50x. Closed-back, good isolation, slightly hyped low end.", |
| 309 |
], |
| 310 |
), |
| 311 |
( |
| 312 |
"Sampling ethics", |
| 313 |
"Where do you draw the line with sampling? Royalty-free packs? Vinyl? Other artists' released music?", |
| 314 |
&[ |
| 315 |
"Royalty-free is fair game obviously. For anything else, clear it or make it unrecognizable.", |
| 316 |
"I only sample stuff I have created myself or bought a license for.", |
| 317 |
"Sampling is an art form. The key is transformation.", |
| 318 |
], |
| 319 |
), |
| 320 |
( |
| 321 |
"When to call a mix done?", |
| 322 |
"I keep tweaking endlessly. How do you know when to stop?", |
| 323 |
&[ |
| 324 |
"When changes become lateral instead of improvements. If you are just going back and forth, stop.", |
| 325 |
"Set a deadline. Ship it. You can always do a v2 later.", |
| 326 |
"Compare to your reference. If it holds up, it is done.", |
| 327 |
"When you start breaking things that were already working.", |
| 328 |
], |
| 329 |
), |
| 330 |
( |
| 331 |
"Learning synthesis from scratch", |
| 332 |
"I have been using presets forever. Want to learn to design my own sounds. Where do I start?", |
| 333 |
&[ |
| 334 |
"Start with subtractive synthesis. One oscillator, one filter, one envelope. Understand what each does.", |
| 335 |
"Syntorial. It is a paid app but it teaches synthesis through ear training, not just theory.", |
| 336 |
"Pick one synth and learn it deeply. Vital or Serum are good because they visualize everything.", |
| 337 |
], |
| 338 |
), |
| 339 |
( |
| 340 |
"Vocal processing chain", |
| 341 |
"What is your typical vocal chain? EQ, compression, de-essing, etc.", |
| 342 |
&[ |
| 343 |
"Gain staging, subtractive EQ, compressor (light 2:1), de-esser, additive EQ, reverb send.", |
| 344 |
"Similar but I add a saturation plugin before the compressor. Gives warmth.", |
| 345 |
"Depends entirely on the vocal and the genre. There is no universal chain.", |
| 346 |
], |
| 347 |
), |
| 348 |
( |
| 349 |
"Budget acoustic treatment", |
| 350 |
"Can I treat a small room for under $200? What should I prioritize?", |
| 351 |
&[ |
| 352 |
"First reflections. Put absorption panels at mirror points on side walls.", |
| 353 |
"Bass traps in the corners are the highest impact single thing you can do.", |
| 354 |
"Rockwool panels in wooden frames. DIY for about $50 per panel.", |
| 355 |
"A thick rug on the floor and heavy curtains help more than people think.", |
| 356 |
], |
| 357 |
), |
| 358 |
( |
| 359 |
"Favorite reverb plugin?", |
| 360 |
"Looking for something versatile. Plates, halls, rooms, all in one.", |
| 361 |
&[ |
| 362 |
"Valhalla Room. $50, sounds amazing, low CPU.", |
| 363 |
"FabFilter Pro-R 2. The decay rate EQ is genius.", |
| 364 |
"Stock reverb in your DAW is probably fine for 90% of use cases.", |
| 365 |
], |
| 366 |
), |
| 367 |
( |
| 368 |
"How important is mastering?", |
| 369 |
"Can I just slap a limiter on the master bus and call it a day?", |
| 370 |
&[ |
| 371 |
"For demos and personal releases, yes. For commercial releases, get it mastered.", |
| 372 |
"Mastering is about perspective. A second set of ears in a treated room catches things you miss.", |
| 373 |
"iZotope Ozone is good enough for DIY mastering if you learn what each module does.", |
| 374 |
], |
| 375 |
), |
| 376 |
( |
| 377 |
"Managing multiple projects at once", |
| 378 |
"I have like 30 unfinished projects. How do you manage the backlog?", |
| 379 |
&[ |
| 380 |
"Pick three. Finish them. Delete the rest. Harsh but effective.", |
| 381 |
"I give each project a status: idea, in progress, mixing, done. Only 2 can be in progress at once.", |
| 382 |
"Set a monthly goal. One finished track per month, minimum.", |
| 383 |
], |
| 384 |
), |
| 385 |
( |
| 386 |
"Track referencing workflow", |
| 387 |
"How do you reference against commercial tracks while mixing?", |
| 388 |
&[ |
| 389 |
"Import the reference directly into the session. Level match with a LUFS meter, A/B constantly.", |
| 390 |
"I use a dedicated plugin that lets me switch between my mix and references with one click.", |
| 391 |
"Listen to the reference on the same speakers, back to back. Do not overthink the workflow.", |
| 392 |
], |
| 393 |
), |
| 394 |
( |
| 395 |
"Gain staging basics", |
| 396 |
"Keep hearing about gain staging but not sure I understand it. ELI5?", |
| 397 |
&[ |
| 398 |
"Every plugin in your chain should receive signal at a reasonable level. If you push hot into a compressor, it behaves differently than if you feed it -18dBFS.", |
| 399 |
"Basically: do not clip anything in the chain before the final limiter. Use trim/gain plugins if needed.", |
| 400 |
"Aim for peaks around -12 to -6 on each channel. Leaves headroom on the master.", |
| 401 |
], |
| 402 |
), |
| 403 |
( |
| 404 |
"Lo-fi production tips", |
| 405 |
"Want to make lo-fi hip hop style beats. What gives that characteristic sound?", |
| 406 |
&[ |
| 407 |
"Bitcrushing, vinyl noise, tape saturation, de-tuned samples, swing on the drums.", |
| 408 |
"Record stuff through a cheap mic or tape deck. Real degradation sounds better than plugins simulating it.", |
| 409 |
"Side-chain the whole mix to the kick. Slow attack, slow release. That pumping effect is key.", |
| 410 |
"Use jazz chord voicings. Maj7, min9, dom13. That is the harmonic foundation.", |
| 411 |
], |
| 412 |
), |
| 413 |
( |
| 414 |
"What's your backup strategy?", |
| 415 |
"Lost a project file last week and it hurt. How do you backup your work?", |
| 416 |
&[ |
| 417 |
"Git for project files, rsync to a NAS for samples and bounces.", |
| 418 |
"Time Machine plus a monthly clone to an external drive.", |
| 419 |
"Cloud sync. Dropbox for active projects, cold storage archive for finished work.", |
| 420 |
"Three copies: local SSD, NAS, off-site. If it does not exist in three places, it does not exist.", |
| 421 |
], |
| 422 |
), |
| 423 |
( |
| 424 |
"Distortion as a creative tool", |
| 425 |
"Using distortion for more than just guitars. What are your favorite ways to use it?", |
| 426 |
&[ |
| 427 |
"Parallel saturation on vocals. Blend in just enough to add presence without obvious distortion.", |
| 428 |
"Run a sub bass through a wavefolder. Instant aggression.", |
| 429 |
"Distort a reverb return. Shoegaze in a box.", |
| 430 |
], |
| 431 |
), |
| 432 |
( |
| 433 |
"Hardware synths worth buying in 2026?", |
| 434 |
"With plugins being so good, is there any reason to buy hardware synths?", |
| 435 |
&[ |
| 436 |
"Workflow. Playing a hardware synth is a different experience than clicking a mouse.", |
| 437 |
"The Korg Minilogue XD is still hard to beat for the price. Four voices, great effects.", |
| 438 |
"I would skip hardware unless you perform live. For studio work, plugins win on convenience.", |
| 439 |
"Elektron Digitone. FM synthesis in a box with an incredible sequencer.", |
| 440 |
], |
| 441 |
), |
| 442 |
( |
| 443 |
"How to get better at arrangement", |
| 444 |
"My loops sound great but full tracks feel flat. Any tips for arrangement?", |
| 445 |
&[ |
| 446 |
"Study arrangements of songs you like. Map them out on paper. Intro, verse, chorus, bridge — note what enters and exits.", |
| 447 |
"Contrast. If the chorus is dense, strip back the verse. Dynamics come from what you remove.", |
| 448 |
"Energy curve. Every section should either build tension or release it. Never stay flat.", |
| 449 |
"Reference tracks. Drop one into your session and match the structure.", |
| 450 |
"Automate everything. Filter sweeps, volume rides, effect sends. Movement keeps the listener engaged.", |
| 451 |
], |
| 452 |
), |
| 453 |
( |
| 454 |
"Mixing in mono", |
| 455 |
"People say to check your mix in mono. Why? And how often should I do it?", |
| 456 |
&[ |
| 457 |
"Phase cancellation. If something disappears in mono, your stereo image has phase issues.", |
| 458 |
"I check mono every 30 minutes during a mix. Just hit the mono button, listen for 10 seconds.", |
| 459 |
"Some clubs play in mono. If your mix falls apart, half your audience hears a broken version.", |
| 460 |
], |
| 461 |
), |
| 462 |
( |
| 463 |
"Best YouTube channels for learning production?", |
| 464 |
"What channels do you actually learn from vs just watch for entertainment?", |
| 465 |
&[ |
| 466 |
"Dan Worrall. No-nonsense, deep technical knowledge, great explanations.", |
| 467 |
"You Suck at Producing. Funny but genuinely educational.", |
| 468 |
"In The Mix. Good for beginners. Covers basics thoroughly.", |
| 469 |
"Pensado's Place for mixing techniques from industry engineers.", |
| 470 |
], |
| 471 |
), |
| 472 |
( |
| 473 |
"Dealing with creative blocks", |
| 474 |
"Have not made anything in two weeks. Everything I start sounds boring. How do you push through?", |
| 475 |
&[ |
| 476 |
"Constraints. Give yourself a rule: only use three sounds, or finish in one hour. Limits breed creativity.", |
| 477 |
"Listen to music outside your genre. Completely different styles can spark unexpected ideas.", |
| 478 |
"Recreate a track you love. You will learn technique and usually branch off into something original.", |
| 479 |
"Take a break. Burnout is real. Come back when you actually want to, not when you feel you should.", |
| 480 |
], |
| 481 |
), |
| 482 |
( |
| 483 |
"Automation tips", |
| 484 |
"What do you automate most in your mixes?", |
| 485 |
&[ |
| 486 |
"Volume. Subtle 1-2dB rides on vocals and leads make a huge difference.", |
| 487 |
"Filter cutoff. Automate a low-pass sweep into the chorus for instant energy lift.", |
| 488 |
"Reverb send. More reverb in quiet sections, less in dense sections.", |
| 489 |
], |
| 490 |
), |
| 491 |
]; |
| 492 |
|
| 493 |
|
| 494 |
let welcome_id = seed_thread(pool, category_id, users[0].id, threads[0].0, true, false).await; |
| 495 |
seed_post(pool, welcome_id, users[0].id, threads[0].1).await; |
| 496 |
for (i, reply) in threads[0].2.iter().enumerate() { |
| 497 |
seed_post(pool, welcome_id, users[(i + 2) % users.len()].id, reply).await; |
| 498 |
} |
| 499 |
|
| 500 |
|
| 501 |
for (idx, (title, body, replies)) in threads.iter().enumerate().skip(1) { |
| 502 |
let author = &users[(idx + 1) % users.len()]; |
| 503 |
let thread_id = seed_thread(pool, category_id, author.id, title, false, false).await; |
| 504 |
seed_post(pool, thread_id, author.id, body).await; |
| 505 |
|
| 506 |
for (i, reply) in replies.iter().enumerate() { |
| 507 |
let replier = &users[(idx + i + 3) % users.len()]; |
| 508 |
seed_post(pool, thread_id, replier.id, reply).await; |
| 509 |
} |
| 510 |
|
| 511 |
|
| 512 |
if idx == 1 { |
| 513 |
seed_long_discussion(pool, thread_id, users).await; |
| 514 |
} |
| 515 |
} |
| 516 |
} |
| 517 |
|
| 518 |
|
| 519 |
async fn seed_music_mixing(pool: &PgPool, category_id: Uuid, users: &[SeedUser]) { |
| 520 |
let threads: &[(&str, &str, &[&str])] = &[ |
| 521 |
( |
| 522 |
"EQ before or after compression?", |
| 523 |
"Classic debate. What is your default chain order and why?", |
| 524 |
&[ |
| 525 |
"Subtractive EQ first to clean up, then compress, then additive EQ to shape.", |
| 526 |
"Depends on the source. Muddy vocal? EQ first. Clean recording? Compress first.", |
| 527 |
"I do both. Light EQ before, heavier shaping after.", |
| 528 |
], |
| 529 |
), |
| 530 |
( |
| 531 |
"Parallel compression techniques", |
| 532 |
"How are you using parallel compression? Just on drums or on everything?", |
| 533 |
&[ |
| 534 |
"Drums and vocals mainly. Crush a copy, blend it in at like -12dB.", |
| 535 |
"I parallel compress the entire mix bus lightly. Adds glue without squashing dynamics.", |
| 536 |
"The NY compression trick on drums is still unbeatable. Heavy compression, blend to taste.", |
| 537 |
], |
| 538 |
), |
| 539 |
( |
| 540 |
"Multiband compression: when to use it?", |
| 541 |
"I never quite know when multiband is the right tool vs a regular compressor.", |
| 542 |
&[ |
| 543 |
"When different frequency ranges need different treatment. A boomy vocal with sibilance needs different ratios for lows and highs.", |
| 544 |
"On the master bus for gentle tonal balancing. Very light ratios, like 1.5:1.", |
| 545 |
"Rarely. Most problems are better solved with EQ. Multiband comp is a precision tool, not a default.", |
| 546 |
], |
| 547 |
), |
| 548 |
( |
| 549 |
"Mixing with saturation", |
| 550 |
"How much saturation do you add and where in the chain?", |
| 551 |
&[ |
| 552 |
"A tiny bit on every channel. Tape emulation at the end of each strip. Adds harmonic richness.", |
| 553 |
"I saturate the mix bus and nothing else. Keeps it cohesive.", |
| 554 |
"Saturation on bass is essential for me. Makes it audible on small speakers.", |
| 555 |
"Early in the chain, before compression. Saturated signals compress differently.", |
| 556 |
], |
| 557 |
), |
| 558 |
( |
| 559 |
"Taming harsh vocals", |
| 560 |
"My vocal recordings always end up harsh around 3-5kHz. De-esser? EQ? Both?", |
| 561 |
&[ |
| 562 |
"Dynamic EQ on the 2-5kHz range. Only dips when it gets harsh, leaves the presence otherwise.", |
| 563 |
"De-esser is specifically for sibilance (6-10kHz). For 3-5kHz harshness, use a dynamic EQ or multiband.", |
| 564 |
"Check your microphone and preamp. Some mics just have a harsh presence peak. A different mic might solve it at the source.", |
| 565 |
], |
| 566 |
), |
| 567 |
( |
| 568 |
"Reverb mixing tips", |
| 569 |
"My reverbs either sound obvious or nonexistent. How do you make them sit right?", |
| 570 |
&[ |
| 571 |
"Pre-delay. 20-50ms of pre-delay separates the dry signal from the reverb and adds clarity.", |
| 572 |
"High-cut the reverb at 6-8kHz. Bright reverb tails make everything washy.", |
| 573 |
"Send to reverb, then EQ the return. Treat the reverb as its own instrument.", |
| 574 |
], |
| 575 |
), |
| 576 |
( |
| 577 |
"Mixing low end: kick and bass coexistence", |
| 578 |
"How do you make the kick and bass work together without one masking the other?", |
| 579 |
&[ |
| 580 |
"Pick one to own the sub frequencies. If the kick has the sub, high-pass the bass at 60Hz. Or vice versa.", |
| 581 |
"Side-chain the bass to the kick. Classic but effective.", |
| 582 |
"Complementary EQ. Boost the kick at 60Hz, cut the bass there. Boost the bass at 100Hz, cut the kick.", |
| 583 |
"In most genres, the kick owns 40-80Hz and the bass lives at 80-200Hz. Arrange them to not compete.", |
| 584 |
], |
| 585 |
), |
| 586 |
( |
| 587 |
"Mix bus processing", |
| 588 |
"What do you put on your mix bus? When do you add it?", |
| 589 |
&[ |
| 590 |
"Gentle glue compressor (SSL style, 2:1, slow attack) from the start. Mix into it.", |
| 591 |
"EQ, compression, slight saturation, limiter. But everything is doing very little. 1-2dB each.", |
| 592 |
"Nothing until the final mix. I want to hear what I actually have before processing it.", |
| 593 |
], |
| 594 |
), |
| 595 |
( |
| 596 |
"Reference level for mixing", |
| 597 |
"What volume level do you monitor at while mixing?", |
| 598 |
&[ |
| 599 |
"Calibrated to 85dB SPL for critical listening. Most of the time I mix around 75dB.", |
| 600 |
"Quiet. If I can have a conversation over the mix, the volume is right.", |
| 601 |
"I check at multiple levels. Low for balance, medium for detail, loud for short reality checks.", |
| 602 |
], |
| 603 |
), |
| 604 |
( |
| 605 |
"Width and stereo imaging", |
| 606 |
"How do you create width in a mix without it collapsing in mono?", |
| 607 |
&[ |
| 608 |
"Keep the center strong (kick, bass, lead vocal, snare). Spread supporting elements.", |
| 609 |
"Use different methods: hard panning, stereo delay, chorus, mid-side EQ. Variety avoids phase issues.", |
| 610 |
"Always check mono. If it sounds thin in mono, your width is relying on phase tricks that cancel.", |
| 611 |
], |
| 612 |
), |
| 613 |
( |
| 614 |
"Handling dynamic range in modern productions", |
| 615 |
"Everything is so compressed now. How do you keep dynamics while still being competitive in loudness?", |
| 616 |
&[ |
| 617 |
"Mix dynamically. Let the mastering engineer handle loudness. That is literally their job.", |
| 618 |
"Automate volume instead of compressing. Ride the fader for consistent level without squashing transients.", |
| 619 |
"Use upward compression. Raises the quiet parts without touching the peaks.", |
| 620 |
], |
| 621 |
), |
| 622 |
( |
| 623 |
"Delay vs reverb for depth", |
| 624 |
"When do you reach for a delay instead of a reverb to create depth?", |
| 625 |
&[ |
| 626 |
"Delay for rhythmic depth (synced to tempo). Reverb for spatial depth (rooms, halls).", |
| 627 |
"Short delays (30-80ms) create depth without the wash of reverb. Great for keeping things tight.", |
| 628 |
"I use both together. Short delay into a reverb return. Best of both worlds.", |
| 629 |
], |
| 630 |
), |
| 631 |
( |
| 632 |
"Panning strategies", |
| 633 |
"Do you follow specific panning rules or go by feel?", |
| 634 |
&[ |
| 635 |
"LCR panning. Hard left, center, hard right. Simple but effective. Forces commitment.", |
| 636 |
"I pan where the instruments would be on a stage. Drums from the drummer's perspective.", |
| 637 |
"By feel. Whatever serves the song. Rules are starting points, not laws.", |
| 638 |
], |
| 639 |
), |
| 640 |
( |
| 641 |
"Mixing with headphones — tips and tricks", |
| 642 |
"For those who primarily mix on headphones, what are your strategies?", |
| 643 |
&[ |
| 644 |
"Crossfeed plugin. Simulates speaker crosstalk so panning sounds more natural.", |
| 645 |
"Reference constantly on speakers when you can. Even laptop speakers reveal balance issues.", |
| 646 |
"Open-back headphones for mixing, closed-back for tracking. The soundstage difference matters.", |
| 647 |
], |
| 648 |
), |
| 649 |
( |
| 650 |
"The loudness war is over — right?", |
| 651 |
"With streaming normalization, does anyone still master to -6 LUFS?", |
| 652 |
&[ |
| 653 |
"EDM and hip hop still push hard. Genre expectations matter more than streaming targets.", |
| 654 |
"The war is over for most genres. I master to -10 to -14 depending on the track.", |
| 655 |
"Yes. And it sounds better. More dynamics, more punch, more musicality. No reason to smash it.", |
| 656 |
], |
| 657 |
), |
| 658 |
]; |
| 659 |
|
| 660 |
for (idx, (title, body, replies)) in threads.iter().enumerate() { |
| 661 |
let author = &users[(idx + 2) % users.len()]; |
| 662 |
let thread_id = seed_thread(pool, category_id, author.id, title, false, false).await; |
| 663 |
seed_post(pool, thread_id, author.id, body).await; |
| 664 |
for (i, reply) in replies.iter().enumerate() { |
| 665 |
let replier = &users[(idx + i + 4) % users.len()]; |
| 666 |
seed_post(pool, thread_id, replier.id, reply).await; |
| 667 |
} |
| 668 |
} |
| 669 |
} |
| 670 |
|
| 671 |
|
| 672 |
async fn seed_music_sound_design(pool: &PgPool, category_id: Uuid, users: &[SeedUser]) { |
| 673 |
let threads: &[(&str, &str, &[&str])] = &[ |
| 674 |
( |
| 675 |
"FM synthesis for beginners", |
| 676 |
"FM synthesis always seemed impenetrable to me. Where do you start?", |
| 677 |
&[ |
| 678 |
"Two operators. Carrier and modulator. Change the ratio between them and listen. That is literally it to start.", |
| 679 |
"Dexed is free and models the DX7. Great for learning because there are tons of tutorials.", |
| 680 |
"Start with simple ratios: 1:1 for warmth, 1:2 for brightness, 1:3 for nasality. Then experiment.", |
| 681 |
], |
| 682 |
), |
| 683 |
( |
| 684 |
"Wavetable synthesis tips", |
| 685 |
"Using Vital/Serum and want to go beyond presets. What are your wavetable tricks?", |
| 686 |
&[ |
| 687 |
"Import your own audio as a wavetable. Record a word, import it, scrub through it with an LFO.", |
| 688 |
"Morph between simple waveforms. A slow morph from saw to square adds movement without being obvious.", |
| 689 |
"Stack two oscillators with different wavetable positions and detune slightly. Instant width.", |
| 690 |
], |
| 691 |
), |
| 692 |
( |
| 693 |
"How to make a supersaw", |
| 694 |
"Every tutorial makes it sound easy but mine never sound as full as professional supersaws.", |
| 695 |
&[ |
| 696 |
"More unison voices, more detune, slight chorus. But the real secret is layering: a supersaw is usually 2-3 layers, not one patch.", |
| 697 |
"High-pass the supersaw and layer a clean sub underneath. The fullness comes from the sub, not the saw.", |
| 698 |
"OTT on the supersaw bus. Controversial but it works.", |
| 699 |
"Mid-side processing. Keep the center mono, spread the sides. Instant width and power.", |
| 700 |
], |
| 701 |
), |
| 702 |
( |
| 703 |
"Granular synthesis — practical uses?", |
| 704 |
"Granular synths look cool but I cannot figure out when to actually use them. What do you use granular for?", |
| 705 |
&[ |
| 706 |
"Pads and textures. Take a field recording, granularize it, and you have a unique atmosphere.", |
| 707 |
"Glitch effects. Short grain size + random position = controlled chaos.", |
| 708 |
"Stretching vocals to infinity. Load a vocal chop, set huge grain size, and you have a drone.", |
| 709 |
], |
| 710 |
), |
| 711 |
( |
| 712 |
"Designing kick drums from scratch", |
| 713 |
"How do you synthesize a kick drum? I always just use samples.", |
| 714 |
&[ |
| 715 |
"Sine wave with a pitch envelope. Start at 200-300Hz, drop to 40-60Hz in about 50ms. Add a click layer for attack.", |
| 716 |
"Three layers: sub (sine, pitch envelope), body (short noise burst, filtered), click (very short transient).", |
| 717 |
"Operator in Ableton can do it in seconds. One sine oscillator, pitch envelope with fast decay.", |
| 718 |
], |
| 719 |
), |
| 720 |
( |
| 721 |
"Making sounds feel organic", |
| 722 |
"My synth patches sound too static and digital. How do you add life?", |
| 723 |
&[ |
| 724 |
"LFOs on everything. Subtle random LFO on pitch, filter, amplitude. Humans are never perfectly steady.", |
| 725 |
"Velocity sensitivity. Map velocity to filter cutoff and amplitude. Changes how it responds to playing.", |
| 726 |
"Record the performance, do not program it. Even mouse-drawn MIDI lacks human timing.", |
| 727 |
"Add noise. A tiny bit of noise mixed in makes digital sounds feel more analog.", |
| 728 |
], |
| 729 |
), |
| 730 |
( |
| 731 |
"Resampling workflow", |
| 732 |
"What is your resampling process? Bounce to audio and re-process?", |
| 733 |
&[ |
| 734 |
"Exactly. Design a sound, bounce it, chop it up, throw it in a sampler, add new processing.", |
| 735 |
"I resample through effects. Play a pad, record it through a reverb and delay, chop the result.", |
| 736 |
"Granular resampling. Take anything, granularize it, it becomes something entirely new.", |
| 737 |
], |
| 738 |
), |
| 739 |
( |
| 740 |
"Favorite Vital patches you have designed", |
| 741 |
"Share your favorite sound you have made in Vital. What was the approach?", |
| 742 |
&[ |
| 743 |
"A pluck using two wavetables with very fast envelope decay, short reverb. Simple but cuts through any mix.", |
| 744 |
"A pad that morphs between 4 wavetable frames with a slow random LFO. Different every time it plays.", |
| 745 |
"A bass using the filter FM feature. Self-oscillating filter modulated by an oscillator. Absolutely nasty.", |
| 746 |
], |
| 747 |
), |
| 748 |
( |
| 749 |
"Foley and field recording for music", |
| 750 |
"Anyone incorporate real-world recordings into their music?", |
| 751 |
&[ |
| 752 |
"All the time. City ambience, rain, coffee shop noise. Layer it under pads for realism.", |
| 753 |
"I record weird objects and use them as percussion. A spoon on a mug, keys jangling, books dropped.", |
| 754 |
"Bird recordings slowed down 10x sound like alien synth pads. Nature is the best sound designer.", |
| 755 |
"Contact microphone on everything. Metal fences, bridges, pipes. Gold mine of textures.", |
| 756 |
], |
| 757 |
), |
| 758 |
( |
| 759 |
"Modular synthesis without hardware", |
| 760 |
"Want to explore modular concepts but cannot afford hardware. Software options?", |
| 761 |
&[ |
| 762 |
"VCV Rack. Free, open source, massive module library. It is basically Eurorack on your computer.", |
| 763 |
"Bitwig's modulation system is semi-modular. Very deep and all built into the DAW.", |
| 764 |
"Max/MSP or Pure Data if you want to go deep. Steep learning curve but unlimited.", |
| 765 |
"Cherry Audio Voltage Modular. Cheaper than real hardware and great module selection.", |
| 766 |
], |
| 767 |
), |
| 768 |
( |
| 769 |
"Designing cinematic impacts and risers", |
| 770 |
"How do you create those massive cinematic impacts and tension risers?", |
| 771 |
&[ |
| 772 |
"Layer, layer, layer. Noise sweep + sub drop + metallic hit + reverb tail = one impact.", |
| 773 |
"Reverse cymbal with rising pitch is the classic riser. Add a filter sweep and noise for intensity.", |
| 774 |
"Record something large. Slam a door. Drop a heavy book. Process it with convolution reverb in a cathedral IR.", |
| 775 |
], |
| 776 |
), |
| 777 |
( |
| 778 |
"Phase distortion synthesis", |
| 779 |
"Casio CZ-series used phase distortion. Anyone still using this technique?", |
| 780 |
&[ |
| 781 |
"Underrated. It is different from FM — smoother harmonics, easier to control.", |
| 782 |
"There are a few VST recreations. CZ V from Arturia is faithful to the originals.", |
| 783 |
"You can sort of approximate it in any synth by modulating the phase of one oscillator with another, but true PD has a distinct character.", |
| 784 |
], |
| 785 |
), |
| 786 |
( |
| 787 |
"Processing drums creatively", |
| 788 |
"Beyond standard mixing, how do you use creative processing on drums?", |
| 789 |
&[ |
| 790 |
"Bit-crush the snare slightly. Adds grit and lo-fi character.", |
| 791 |
"Send drums to a reverb, compress the reverb return hard. Massive room sound.", |
| 792 |
"Granular processing on a drum loop. Freeze interesting moments, stretch hits into textures.", |
| 793 |
"Run the whole drum bus through a guitar amp sim. Instant rock energy.", |
| 794 |
], |
| 795 |
), |
| 796 |
( |
| 797 |
"Additive synthesis — is it practical?", |
| 798 |
"Additive seems powerful in theory but is it actually useful for sound design?", |
| 799 |
&[ |
| 800 |
"Very useful for evolving pads and organ-like tones. Direct control over individual harmonics.", |
| 801 |
"Resynthesis is where additive shines. Analyze a sound, then modify individual partials.", |
| 802 |
"In practice, subtractive and wavetable get you there faster. Additive is more of a research tool.", |
| 803 |
], |
| 804 |
), |
| 805 |
( |
| 806 |
"Sound design for games vs music", |
| 807 |
"Anyone here do game audio? How is the process different from music production?", |
| 808 |
&[ |
| 809 |
"Everything needs to loop seamlessly. And sounds need to work at different pitches and speeds for real-time variation.", |
| 810 |
"Much more focus on functionality. A UI click needs to be satisfying but not distracting. Very different from making a synth lead.", |
| 811 |
"Middleware like FMOD or Wwise adds a whole layer of implementation. You are not just making sounds, you are programming behaviors.", |
| 812 |
], |
| 813 |
), |
| 814 |
]; |
| 815 |
|
| 816 |
for (idx, (title, body, replies)) in threads.iter().enumerate() { |
| 817 |
let author = &users[(idx + 5) % users.len()]; |
| 818 |
let thread_id = seed_thread(pool, category_id, author.id, title, false, false).await; |
| 819 |
seed_post(pool, thread_id, author.id, body).await; |
| 820 |
for (i, reply) in replies.iter().enumerate() { |
| 821 |
let replier = &users[(idx + i + 6) % users.len()]; |
| 822 |
seed_post(pool, thread_id, replier.id, reply).await; |
| 823 |
} |
| 824 |
} |
| 825 |
} |
| 826 |
|
| 827 |
|
| 828 |
async fn seed_long_discussion(pool: &PgPool, thread_id: Uuid, users: &[SeedUser]) { |
| 829 |
let posts = [ |
| 830 |
"Been on Ableton since version 8. Cannot imagine switching at this point.", |
| 831 |
"I tried Bitwig for a month. The modulation system is amazing but I missed Ableton's workflow.", |
| 832 |
"Reaper deserves more love. The customization is insane once you learn ReaScript.", |
| 833 |
"FL Studio's piano roll is still the best. Nothing else comes close for MIDI editing.", |
| 834 |
"Logic's Drummer track is legitimately good. Saves me hours on demo tracks.", |
| 835 |
"Has anyone tried Ardour? Curious about the open source option.", |
| 836 |
"Ardour is great for recording and mixing. Less so for electronic production.", |
| 837 |
"Studio One has the best drag-and-drop workflow. Everything just snaps where you want it.", |
| 838 |
"I use different DAWs for different tasks. Ableton for production, Reaper for mixing, FL for beats.", |
| 839 |
"That sounds exhausting. I would rather master one tool than juggle three.", |
| 840 |
"Cubase is still king for film scoring. The expression maps and articulation system are unmatched.", |
| 841 |
"Pro Tools is dead for everything except professional studios that need industry compatibility.", |
| 842 |
"Hot take: the DAW matters way less than people think. Spend that energy on learning mixing.", |
| 843 |
"Agree. I have heard incredible music made in every DAW. And terrible music too.", |
| 844 |
"The best DAW is the one you know. Switching costs months of productivity.", |
| 845 |
"I switch between FL and Ableton depending on the genre. Hip hop in FL, electronic in Ableton.", |
| 846 |
"Reason had so much potential. Shame it never gained traction against the big players.", |
| 847 |
"Anyone using hardware-only setups? No DAW at all?", |
| 848 |
"I did a hardware-only album last year. It was liberating but the mixdown was painful.", |
| 849 |
"Renoise. Tracker workflow is incredibly fast once you learn the key commands.", |
| 850 |
"I miss trackers. Something about the vertical scrolling interface makes rhythm programming intuitive.", |
| 851 |
"What about Maschine or MPC as a DAW? Those have gotten pretty capable.", |
| 852 |
"MPC standalone is great for jamming but I always end up exporting to a proper DAW for mixing.", |
| 853 |
"Bitwig on Linux is underrated. Full native support, no WINE hacks.", |
| 854 |
"I produce on Linux with Bitwig. Works perfectly. Even plugin support is solid with yabridge.", |
| 855 |
"The iPad is becoming a legit production platform. GarageBand to Logic transition is seamless now.", |
| 856 |
"Mobile production is fun for sketching ideas but I would not mix on a tablet.", |
| 857 |
"Anyone tried the new AI features in some DAWs? Stem separation, auto-mixing, etc.", |
| 858 |
"AI stem separation is useful for sampling. The mixing AI is gimmicky.", |
| 859 |
"I use LALAL.ai for stem extraction. Better results than the built-in DAW tools.", |
| 860 |
"The plugin format wars are annoying. VST3, AU, CLAP. Can we just pick one?", |
| 861 |
"CLAP is the future. Open standard, better multithreading, no licensing fees.", |
| 862 |
"VST3 is fine. It works everywhere. CLAP is cool but the ecosystem is not there yet.", |
| 863 |
"AU is Apple-only, so it is irrelevant for anyone on Windows or Linux.", |
| 864 |
"Reaper supports everything. VST2, VST3, AU, CLAP, JS, LV2. No format wars needed.", |
| 865 |
"Honestly the DAW you start with tends to be the one you stick with. The muscle memory runs deep.", |
| 866 |
"I started on GarageBand, moved to Logic, tried Ableton, came back to Logic. Full circle.", |
| 867 |
"FL Studio's lifetime free updates are unbeatable. Paid once in 2015, still getting new versions.", |
| 868 |
"That is genuinely impressive. No other DAW offers that deal.", |
| 869 |
"The subscription model some companies are pushing is concerning. I want to own my tools.", |
| 870 |
"Agree. If the company shuts down, subscriptions die. Perpetual licenses survive.", |
| 871 |
"Ableton's standard-to-suite upgrade price is brutal though. Almost the cost of a new DAW.", |
| 872 |
"Wait for sales. Ableton does 20-25% off once or twice a year.", |
| 873 |
"I use the DAW that came free with my audio interface. Ableton Lite. It is enough for what I do.", |
| 874 |
"Lite versions are a great starting point. Upgrade when you hit the track limit.", |
| 875 |
"Track limits are artificial but they do force you to commit and bounce stems.", |
| 876 |
"Anyone still using Cakewalk? It went free and then got acquired again.", |
| 877 |
"Cakewalk is solid but the UI feels dated compared to modern DAWs.", |
| 878 |
"UI matters more than people admit. You stare at this thing for hours. It should look good.", |
| 879 |
"Function over form. I will take ugly and fast over pretty and slow any day.", |
| 880 |
"My dream DAW would have Ableton's session view, FL's piano roll, Logic's stock plugins, and Reaper's customization.", |
| 881 |
"So basically everything good from everything. Not unreasonable honestly.", |
| 882 |
"The DAW market is mature enough that they are all good. Pick one and make music.", |
| 883 |
"This thread has been going for a while. I think the conclusion is: whatever works for you.", |
| 884 |
"Final answer: all DAWs are good. Now go make music instead of debating tools.", |
| 885 |
]; |
| 886 |
|
| 887 |
for (i, body) in posts.iter().enumerate() { |
| 888 |
let author = &users[(i + 4) % users.len()]; |
| 889 |
seed_post(pool, thread_id, author.id, body).await; |
| 890 |
} |
| 891 |
} |
| 892 |
|
| 893 |
|
| 894 |
|
| 895 |
async fn seed_community(pool: &PgPool, name: &str, slug: &str, description: Option<&str>) -> Uuid { |
| 896 |
sqlx::query_scalar( |
| 897 |
"INSERT INTO communities (name, slug, description) |
| 898 |
VALUES ($1, $2, $3) |
| 899 |
ON CONFLICT (slug) DO UPDATE SET name = EXCLUDED.name |
| 900 |
RETURNING id", |
| 901 |
) |
| 902 |
.bind(name) |
| 903 |
.bind(slug) |
| 904 |
.bind(description) |
| 905 |
.fetch_one(pool) |
| 906 |
.await |
| 907 |
.expect("failed to seed community") |
| 908 |
} |
| 909 |
|
| 910 |
async fn seed_category( |
| 911 |
pool: &PgPool, |
| 912 |
community_id: Uuid, |
| 913 |
name: &str, |
| 914 |
slug: &str, |
| 915 |
sort_order: i32, |
| 916 |
description: Option<&str>, |
| 917 |
) -> Uuid { |
| 918 |
sqlx::query_scalar( |
| 919 |
"INSERT INTO categories (community_id, name, slug, description, sort_order) |
| 920 |
VALUES ($1, $2, $3, $4, $5) |
| 921 |
ON CONFLICT (community_id, slug) DO UPDATE SET name = EXCLUDED.name |
| 922 |
RETURNING id", |
| 923 |
) |
| 924 |
.bind(community_id) |
| 925 |
.bind(name) |
| 926 |
.bind(slug) |
| 927 |
.bind(description) |
| 928 |
.bind(sort_order) |
| 929 |
.fetch_one(pool) |
| 930 |
.await |
| 931 |
.expect("failed to seed category") |
| 932 |
} |
| 933 |
|
| 934 |
async fn seed_membership(pool: &PgPool, user_id: Uuid, community_id: Uuid, role: CommunityRole) { |
| 935 |
sqlx::query( |
| 936 |
"INSERT INTO memberships (user_id, community_id, role) |
| 937 |
VALUES ($1, $2, $3) |
| 938 |
ON CONFLICT (user_id, community_id) DO NOTHING", |
| 939 |
) |
| 940 |
.bind(user_id) |
| 941 |
.bind(community_id) |
| 942 |
.bind(role.as_str()) |
| 943 |
.execute(pool) |
| 944 |
.await |
| 945 |
.expect("failed to seed membership"); |
| 946 |
} |
| 947 |
|
| 948 |
async fn seed_membership_upsert(pool: &PgPool, user_id: Uuid, community_id: Uuid, role: CommunityRole) { |
| 949 |
sqlx::query( |
| 950 |
"INSERT INTO memberships (user_id, community_id, role) |
| 951 |
VALUES ($1, $2, $3) |
| 952 |
ON CONFLICT (user_id, community_id) DO UPDATE SET role = EXCLUDED.role", |
| 953 |
) |
| 954 |
.bind(user_id) |
| 955 |
.bind(community_id) |
| 956 |
.bind(role.as_str()) |
| 957 |
.execute(pool) |
| 958 |
.await |
| 959 |
.expect("failed to seed membership"); |
| 960 |
} |
| 961 |
|
| 962 |
async fn seed_thread( |
| 963 |
pool: &PgPool, |
| 964 |
category_id: Uuid, |
| 965 |
author_id: Uuid, |
| 966 |
title: &str, |
| 967 |
pinned: bool, |
| 968 |
locked: bool, |
| 969 |
) -> Uuid { |
| 970 |
sqlx::query_scalar( |
| 971 |
"INSERT INTO threads (category_id, author_id, title, pinned, locked) |
| 972 |
VALUES ($1, $2, $3, $4, $5) |
| 973 |
RETURNING id", |
| 974 |
) |
| 975 |
.bind(category_id) |
| 976 |
.bind(author_id) |
| 977 |
.bind(title) |
| 978 |
.bind(pinned) |
| 979 |
.bind(locked) |
| 980 |
.fetch_one(pool) |
| 981 |
.await |
| 982 |
.expect("failed to seed thread") |
| 983 |
} |
| 984 |
|
| 985 |
async fn seed_post( |
| 986 |
pool: &PgPool, |
| 987 |
thread_id: Uuid, |
| 988 |
author_id: Uuid, |
| 989 |
body_markdown: &str, |
| 990 |
) -> Uuid { |
| 991 |
let body_html = body_markdown |
| 992 |
.split("\n\n") |
| 993 |
.map(|p| { |
| 994 |
let escaped = p |
| 995 |
.replace('&', "&") |
| 996 |
.replace('<', "<") |
| 997 |
.replace('>', ">"); |
| 998 |
format!("<p>{escaped}</p>") |
| 999 |
}) |
| 1000 |
.collect::<String>(); |
| 1001 |
|
| 1002 |
let post_id: Uuid = sqlx::query_scalar( |
| 1003 |
"INSERT INTO posts (thread_id, author_id, body_markdown, body_html) |
| 1004 |
VALUES ($1, $2, $3, $4) |
| 1005 |
RETURNING id", |
| 1006 |
) |
| 1007 |
.bind(thread_id) |
| 1008 |
.bind(author_id) |
| 1009 |
.bind(body_markdown) |
| 1010 |
.bind(&body_html) |
| 1011 |
.fetch_one(pool) |
| 1012 |
.await |
| 1013 |
.expect("failed to seed post"); |
| 1014 |
|
| 1015 |
sqlx::query("UPDATE threads SET last_activity_at = now() WHERE id = $1") |
| 1016 |
.bind(thread_id) |
| 1017 |
.execute(pool) |
| 1018 |
.await |
| 1019 |
.expect("failed to update thread activity"); |
| 1020 |
|
| 1021 |
post_id |
| 1022 |
} |
| 1023 |
|