diff --git a/.github/workflows/studio-checks.yml b/.github/workflows/studio-checks.yml new file mode 100644 index 0000000..300488f --- /dev/null +++ b/.github/workflows/studio-checks.yml @@ -0,0 +1,37 @@ +name: Studio checks +on: + pull_request: + workflow_dispatch: +jobs: + studio: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: npm + cache-dependency-path: tools/webui/package-lock.json + - run: npm ci + working-directory: tools/webui + - run: npm ci + working-directory: tools/youtube-agent + - run: npm run check + working-directory: tools/webui + - run: node --experimental-strip-types --test tests/*.test.mjs + working-directory: tools/webui + - run: npm test + working-directory: tools/youtube-agent + - run: npm run build + working-directory: tools/webui + - run: npx playwright install --with-deps chromium + working-directory: tools/youtube-agent + - run: node tests/studio-interactions.mjs + - run: node tests/workflow-browser.mjs + - run: node tests/archive-native.mjs + - run: node tools/webui/tests/storage-browser.mjs + - uses: actions/upload-artifact@v4 + if: always() + with: + name: studio-review + path: build/ui-review diff --git a/.gitignore b/.gitignore index 8954277..b7e0df4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,24 @@ build/ *.wav tests/*/ +!tests/job-archive/ checkpoints/ models/*.gguf __pycache__/ node_modules/ +saved_presets/ +job_results/ tools/webui/dist/ training/datasets/ training/checkpoints/ + +# Local operational state and user media +/tools/youtube-agent/profile/ +/tools/youtube-agent/runs/ +*.mp4 +/server*.log + +.venv-vocal/ + +/pinokio_agent/ diff --git a/AUDIT_REPAIRS.md b/AUDIT_REPAIRS.md new file mode 100644 index 0000000..94300fb --- /dev/null +++ b/AUDIT_REPAIRS.md @@ -0,0 +1,49 @@ +> Current implementation, acceptance evidence and build/recovery instructions: [Studio release guide]( docs/studio-release.md ). This document records earlier planning or audit findings. + +# Audit repair status + +## Implemented + +- Atomic browser-library job saves; recovery is cleared after commit, retry saves are deduplicated by source job. +- MP3 default 320 kbps; returned job format determines song metadata. +- Installed Ollama model discovery, lyric draft review, cancellation/timeout, unload request after inference. +- Complete YAML lyric engines loaded into prompts; malformed inline YAML fixed. +- Separate music and lyric mixers with angular, keyboard and numeric 0–100 controls. +- Zero influence excludes a style; removal updates the music prompt. Music descriptions are included in that prompt. +- Active blends persist across reloads. Manually edited/imported music prompts invalidate stale music rings. +- Separate saved music/lyric blends: save, load, explicit update, rename, confirmed delete. Legacy music favourites remain intact and are imported when no new-format favourites exist. +- Auto-duration explicitly submits zero; ordinary saved/imported durations are preserved. +- At most four pending native jobs (including the executing job); excess submissions return HTTP 429. +- Generation request cap 1 MiB; steps 1–200, duration 0–600 seconds, CFG -1–30, peak clip 0–999, supported MPEG bitrates only. +- Worker catches C++ exceptions and marks affected jobs failed; queued cancellation avoids model work. This cannot recover from native assertions, access violations or driver failures. +- Localhost server default and launcher binding. Explicit --host remains available for deliberate LAN use; no authentication layer added. + +## Verification + +From tools/webui: `npm run check`, `node --test tests/repair-regression.test.mjs`, `npm run build`. + +Native release candidate: `build/audit-repair/yue-server.exe` plus its sibling DLLs. Build target yue-server with MSBuild OutDir set to that directory. + +From repository root: `node tests/server-smoke.mjs` starts a separate CPU-only server on port 18087, checks defaults and rejected requests, then stops only its own child. The test does not generate music. + +## Deployment and remaining work + +### Track artwork viewer + +Deployed 2026-09-23 with explicit restart approval; previous binaries: build/backup-before-artwork-viewer-20260923-122024. Songs now support an optional artwork Blob in IndexedDB. The track menu offers Add/Replace artwork (PNG/JPEG/WebP, max 20 MB and 64 MP); validation and saving finish before the existing artwork changes. Art displays as a square beside the track with a separate playback button. Clicking it opens a native modal with thumbnail-to-image Web Animations morph, reverse close, keyboard Escape/focus restoration, scroll lock, full-image download and reduced-motion support. Blob URLs are revoked on cleanup. Automatic artwork generation is still not connected; a future generator should attach its resulting image Blob to Song.artwork and save the track. + +Verified: six regression tests, clean frontend checks, production/native builds, isolated desktop/mobile browser upload-and-reload persistence, active morph animation, Escape/close button, focus and scroll restoration, reduced-motion behavior, screenshots and live embedded-UI markers. GPU-backed native server starts with the existing 320 kbps default. No user library data was used in browser tests. + +### Modern studio UI + +Deployed 2026-09-23 after a second explicit restart approval. Previous binaries: build/backup-before-modern-ui-20260923-112727. Modern theme-aware surfaces, decorative waveform animation, responsive header, section shortcuts, record-sleeve empty state, library search and favourite filtering. Motion respects prefers-reduced-motion; the activity indicator now reflects actual log connectivity. No remote assets or new dependencies. + +Verification: Svelte check has no errors/warnings; five existing regression tests pass; production/native builds and temporary-server smoke checks pass. `node tests/studio-browser.mjs` from tools/webui tested all five themes, desktop/mobile overflow, ring add/remove and keyboard controls, render navigation, reduced motion, library search and favourites, with no runtime exceptions. Isolated-profile screenshots: build/ui-review. Live port 8087 serves the new UI with the 320 kbps default and CUDA initialization intact. + +Deployed on 2026-09-23 after the user confirmed tracks were saved and approved restarting. Candidate executable and four GGML DLLs were copied into build/Release. Previous binaries are retained in build/backup-before-audit-20260923-110222. The existing music launcher continues to use build/Release through server.cmd. + +Live verification: health OK on localhost:8087, MP3 default 320 kbps, native 48 kHz, Q8_0 backbone and F32 YuE2 VAE unchanged, CUDA0 initialization successful, updated embedded UI present, all five deployed binary hashes match the tested candidate. No new song was generated during deployment. + +Not yet verified: interactive browser pointer/keyboard/favourite workflows, song-generation quality, actual Ollama lyric generation on installed models, VRAM recovery under load, admission-limit stress or worker-failure injection. + +Still pending: durable server-side song recovery, broader library backup, full pipeline/plugin architecture, mastering, album/artwork/MP4 processing, all end-to-end audio scenarios. The existing album/artwork controls remain placeholders. Browser-only concurrency guards do not coordinate separate tabs or applications. diff --git a/PROJECT_BUILD_PLAN.md b/PROJECT_BUILD_PLAN.md new file mode 100644 index 0000000..74d966b --- /dev/null +++ b/PROJECT_BUILD_PLAN.md @@ -0,0 +1,164 @@ +> Current implementation, acceptance evidence and build/recovery instructions: [Studio release guide]( docs/studio-release.md ). This document records earlier planning or audit findings. + +# YuE2 Studio - project update and resume plan + +Updated: 2026-09-23. Work parked at the user's request; no background upgrade or restart scheduled. + +## Project identity and safety + +- Correct project: `C:\Users\mrmul\yue2.cpp`, NOT Maestro. +- PowerShell `music` launches `server.cmd`, then `build/Release/yue-server.exe`; UI is served on localhost:8087. +- Native C++/GGML generation with embedded Svelte UI. Preserve the working YuE2 Q8_0 model, compatible native F32 VAE, and 48 kHz audio path. +- The worktree contains substantial existing modifications and untracked features. Do not reset, clean, or overwrite them. +- No huge model downloads, security-policy weakening, or unrelated app updates without explicit approval. +- Before a future YuE2 deployment, ask the user to save new tracks and approve restarting: server-only results can be lost. Previous approvals were for previous deployments. + +## Current status: distinguish deployed from draft + +### Previously deployed and tested + +- Modern studio UI and five themes; separate music and lyric blend controls and saved favourites. +- Ollama integration and structured lyric-style engines (real model output quality still needs end-to-end evaluation). +- MP3 default 320 kbps, existing WAV options, request validation and job persistence repairs. +- Uploaded artwork attached to songs: square thumbnail, expanding modal/morph, image download, keyboard and reduced-motion support. +- See `AUDIT_REPAIRS.md` for historical test/deployment evidence and limitations. Those passes do not validate the new album work. + +### Draft source only: not complete, tested, or deployed + +- `tools/webui/src/lib/album-types.ts`: album/track state and persisted job IDs. +- `tools/webui/src/lib/album-db.ts`: separate IndexedDB album storage. +- `tools/webui/src/lib/album-plan.ts`: lyric imports, request snapshots, shared art direction and per-track seeds. +- `tools/webui/src/lib/comfy-art.ts`: proposed Qwen 2.1 graph, readiness, submission, polling and reference upload. +- `tools/comfy-api.h`: restricted loopback ComfyUI API bridge; wired into `tools/yue-server.cpp` with a configurable Comfy port. +- Song type extensions and Vite proxy changes support future album/art/video integration. +- `pinokio_agent/skills/api/inteliweb-comfyui/SKILL.md`: reusable Comfy API notes. +- Album runner, real album UI, MP4 encoding, and end-to-end artwork generation are unfinished. Existing album controls must not be presented as functioning features yet. + +## Immediate blocker: ComfyUI upgrade + +Managed installation: `C:\pinokio\api\inteliweb-comfyui\app` (Pinokio app `inteliweb-comfyui`, last ready endpoint localhost:8188). Rediscover/probe via the Pinokio skill on return rather than assuming it is running. + +User approved installing a compatible GGUF loader through its manager, restarting ComfyUI if necessary, and upgrading its core through the manager with a backup. This does not authorize changing network/security policies or downloading large weights. + +- Installed/running core remained **0.34.0**, revision `f938505952476e48a12687eac696cdc94d48a3fe`. +- Manager snapshot and backup completed successfully. +- Manager update was accepted but then failed: `Failed to fetch ComfyUI` / `ComfyUI update failed`. +- Elevated read-only GitHub Git probe also timed out connecting to `github.com:443` after about 21 seconds. GitHub's API endpoint was reachable; this is not proof Git transport works. +- No restart, DNS/proxy changes, remote changes, or security bypass was performed. YuE2 health remained OK. + +### Backup + +`build/comfy-backup-20260923-130946/` + +- `comfy-core.bundle`: original source revision, NOT a full Python environment backup. +- `manager-snapshot.json`: core/custom-node revisions and installed dependency versions. +- `user/`: user settings/workflows/manager state. +- `requirements.txt` and `RESTORE-NOTES.md`. + +Keep this backup. Prefer manager-supported snapshot recovery if needed; do not blindly reset repositories or overwrite newer user workflows. + +### Resume checklist: GitHub and compatible core + +1. Read this plan, `AUDIT_REPAIRS.md`, and the Pinokio skill. Inspect current changes and confirm both apps' identities/status. +2. Check whether GitHub Git connectivity has recovered. If still failing, diagnose read-only first; ask before network configuration changes or using a different installation method. +3. Confirm ComfyUI's image queue and manager queue are idle. Refresh the backup if user state changed since this snapshot. +4. Retry the core update through the supported manager; inspect worker logs, not just HTTP 200. Select a supported release containing native Qwen Image 2.1 support; recheck current compatibility rather than hard-coding a stale release. +5. Check dependency installation and restart ComfyUI via its supported managed lifecycle. Verify `/system_stats`, `/object_info`, and startup errors. +6. Require `TextEncodeQwenImage21` and the correct 2.1 model implementation. Older Qwen Edit nodes are not substitutes. +7. Install a genuinely compatible GGUF loader through the manager. Prior inspection found the model-recommended leejet fork supports the architecture, while the inspected city96 loader did not. Reverify upstream state. If the required fork is blocked by the manager's custom-URL policy, ask for direction; do not disable that protection or bypass it with a clone. +8. Confirm all installed model dropdowns, validate a minimal graph, and then run an explicitly identified artwork smoke test. Node presence alone is not an inference pass. + +### Installed model files observed (recheck before use) + +- `models/diffusion_models/qwen-image-2.1-Q4_K_M.gguf` +- `models/text_encoders/qwen3vl_8b_int8_convrot.safetensors` +- `models/vae/qwen_image_2.1_vae_bf16.safetensors` + +The requested Heretic GGUF text encoder was NOT found. Do not claim it is in use. The proposed graph uses the installed compatible INT8 encoder, on CPU where supported. The machine has an RTX 4060 Laptop GPU with 8 GB VRAM and approximately 16 GB RAM; actual memory pressure and inference performance need measurement. + +References to recheck: + +- https://github.com/Comfy-Org/ComfyUI +- https://github.com/Comfy-Org/workflow_templates/blob/main/templates/image_qwen_image_2_1_t2i.json +- https://github.com/Comfy-Org/workflow_templates/blob/main/templates/image_qwen_image_2_1_image_edit.json +- https://huggingface.co/abenzerps/Qwen-Image-2.1-Uncensored-GGUF + +## Build milestones after compatibility is restored + +### 1. Resumable album orchestration + +- Upload multiple UTF-8 lyric files; editable titles, order and optional per-song art direction. +- Snapshot music settings; clear reused semantic tokens/score data; generate one song at a time. +- Persist stage and job IDs before polling; commit song data before advancing. Resume without regenerating already saved songs. +- Coordinate album/single-song runs and multiple tabs. Pause after the current item; never cancel another app user's Comfy work. +- Preserve completed music if optional artwork/video fails. Give explicit retry and audio-only choices. + +### 2. Consistent but distinct artwork + +- Generate one master album cover from shared art direction, palette, medium and lyrical themes. +- Reference the master cover for each track, with different lyric-derived subjects and seeds. Do not chain references through preceding tracks, which can drift. +- Store resulting image Blobs on albums/songs and reuse the deployed thumbnail/viewer. +- Stage work to reduce model competition: sequential songs, cover, per-song artwork, then optional video. Check queues before unloading models. +- Validate actual reference conditioning and image quality. Consistency is guidance, not a guarantee; offer preview/retry. +- Investigate current upstream Qwen 2.1 reference-latent issues before choosing canvas/reference settings. + +### 3. Optional MP4 export + +- Resolve FFmpeg through managed tool discovery/configuration (previously found under Pinokio's miniforge), not a hard-coded module path. +- Add a bounded asynchronous video job: track artwork plus audio, 1080p H.264/AAC with broadly compatible pixel format and fast-start metadata. +- Use safe subprocess argument handling, unique temporary paths, input limits, clear errors and deliberate cleanup. +- Preserve the original MP3/WAV and image. MP3 default remains 320 kbps; AAC video audio is a separate encode, not a lossless quality upgrade. +- Expose video availability and per-track download; do not show an enabled option without a functioning encoder. + +### 4. Album UI and usability + +- Replace placeholders with a collapsible Create Album workspace: track queue, shared visual direction, artwork toggle, optional MP4 toggle, readiness and progress. +- Saved albums/resume, cover preview, per-track audio/art/video status and understandable failures. +- Keep music style and lyric construction separate. Preserve existing themes, ring controls, favourites and generation workflows. +- Explain whether the browser must stay open during orchestration. Do not promise background processing until implemented and tested. + +### 5. Verification and deployment gates + +- Unit tests: import validation, request isolation, deterministic prompts/seeds, state transitions, retry/deduplication, persistence failures. +- Integration tests: missing Comfy/model/loader, failed/restarted job, concurrent work, pause/resume, malformed uploads, video failures, all optional features OFF. +- Real end-to-end test: at least two short songs, one master cover, two distinct reference-conditioned images, MP3 metadata and playable MP4s; inspect visual coherence, audio validity and peak memory. +- Re-run frontend checks/regressions, production/native builds, server smoke tests and isolated browser tests. Existing smoke tests do not prove music/image generation quality. +- Inspect mobile layout, keyboard/focus, reduced motion, theme contrast and image persistence after reload. +- Request fresh YuE2 restart approval; back up deployed binaries, deploy only the tested candidate, verify health/UI/model paths, and document exact results and remaining limitations. + +Useful existing commands: + +```text +# From tools/webui +npm run check +node --test tests/repair-regression.test.mjs +npm run build +node tests/studio-browser.mjs + +# From repository root, after rebuilding the candidate +node tests/server-smoke.mjs +``` + +Build native candidate to `build/audit-repair`, leaving the running executable alone. On this Windows setup, normalize duplicate Path/PATH environment keys before invoking MSBuild. Read existing test harnesses before running: browser tests should use isolated profiles/fixtures, not user library data. + +## Later roadmap (not delivered by the album work) + +Re-audit the original enhancement specification before implementing: processor registry, model lifecycle manager, serializable configuration, safe decoder selection, genuine mastering DSP, optional restoration/separation/stem processing/RAVE/detail recovery/style-transfer adapters, A/B playback, and broader recovery/backup. Expose only controls backed by real implementations. Keep all enhancements optional and retain YuE2's compatible native decoder. + +## Suggested resume instruction + +"Resume YuE2 from PROJECT_BUILD_PLAN.md. Check GitHub connectivity, finish the approved manager-based ComfyUI compatibility upgrade with the backup preserved, then continue the tested album/artwork/MP4 milestones. Do not modify Maestro or restart YuE2 without fresh approval." + +## Signal Studio update — 2026-09-24 + +Deployed on 2026-09-24 after explicit approval for this update. Live process at verification: PID 10876 on 127.0.0.1:8087. + +- Canvas visualizer: ribbon, orbit and logarithmic spectrum views; actual playback analysis, bass/body/air meters, native-dialog expanded view, Escape/focus restoration, reduced-motion and offscreen rendering limits. +- Creation desk: numbered navigation, searchable preset chips and existing influence rings, separate lyric section, collapsible local lyric assistant and score editor, compact sampling controls and a production summary. Removed the unfinished album input placeholders from the active form. +- Automatic production uses conservative weighted score-temperature presets (0.65 rhythmic / 0.70 balanced / 0.75 expressive, relative to the model default). Semantic sampling, CFG, flow steps and normalization use the model defaults; MP3 is 320 kbps. Manual mode, explicit imported settings, replay codes, seeds, durations and batches are preserved. These presets are not empirically proven genre optima. +- Validation: Svelte check 0 errors/warnings; 8 regression tests; production build; isolated browser tests covering actual muted PCM playback, mode controls, mobile/themes, automatic/manual submitted request capture and reload persistence; native candidate build; temporary CPU server smoke pass. No song was generated to evaluate preset quality. +- Candidate: `build/audit-repair/yue-server.exe` (matching `Release/yue-server.exe` inside candidate). +- Screenshots: `build/ui-review/studio-mint.png`, `signal-live.png`, `signal-orbit.png`, `production-desk.png`, `studio-mobile.png`. +- Backup: `build/backup-before-signal-studio-20260924-202647/`. Only the executable changed during deployment; all four backend DLL hashes matched the tested candidate. +- Live validation: `/health` OK; compressed production HTML contains the new visualizer, production engine, style search and automatic profiles. Live executable SHA256 matches candidate: `753B810125F7FDFDF38B2A8E5AB8523465E51B8900F1B74524EE3924491366E4`. +- Existing browser tabs need a reload to use the new build. This update does not finish the separate album/artwork/video roadmap above. diff --git a/README.md b/README.md index 4d8e8d5..a6f1b95 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,35 @@ Transcribe score or Transcribe melody from the card menu: the score lands in the score field, pick the matching mode, add your lyrics and a style, and the model covers the song. +## Vocal level adjustment + +The song decoder produces a single stereo mix. The card menu can separate +that mix into vocals and accompaniment, estimate an automatic vocal gain, or +set the gain manually from -6 to +6 dB, then remix the result. Auto compares +400 ms vocal-active sections and is a starting point rather than a style-aware +mixing standard. The original stays in the library for comparison. This uses +the local `python-audio-separator` command and FFmpeg; separation can take time +and may add artifacts. + +On Windows with an NVIDIA GPU, install the helper once from this folder: + +```powershell +.\setup-vocal-separation.ps1 +``` + +The selected BS-RoFormer model is downloaded on the first adjustment. Keep +FFmpeg available on `PATH`; the helper's environment report shows whether its +CUDA provider is available. You can still generate songs without this optional +helper. + +## Library backup + +Use **Backup** above the track list to download a ZIP containing saved tracks, +audio, optional artwork/video, and supported browser preferences. **Restore** +checks the archive contents before showing a confirmation; accepting replaces +the current track library. Keep backups somewhere outside the browser profile +if you want to protect them from browser data cleanup. + ## Pipeline ``` diff --git a/docs/PRODUCER_CONTROLS.md b/docs/PRODUCER_CONTROLS.md new file mode 100644 index 0000000..b07c132 --- /dev/null +++ b/docs/PRODUCER_CONTROLS.md @@ -0,0 +1,17 @@ +# Song planner and voices + +The Create page includes a persistent song planner for new compositions. It compiles musical direction into the existing YuE2 style prompt; no model weights or inference defaults change. + +- Singing amount guides melodic singing versus rap/spoken delivery. Vocal presence separately guides the balance of vocal passages and instrumental space. These are requested proportions, not enforced timing. +- Vocal presence zero submits empty lyrics while preserving the editor text. +- One to four requested voices have editable descriptions. Locking keeps descriptions and cast size fixed in the browser across songs and reloads. This is a profile lock, not a speaker identity embedding, voice clone, or guarantee of the same singer. +- Tempo, arrangement, vocal descriptions, and delivery guide both music and the Ollama lyric assistant. Existing lyrics are never rewritten automatically. The plan is a transparent template or user-written direction, not a validated symbolic score. +- Auto duration uses a rough 4/4 phrase budget from tempo, words per line, singing balance and vocal presence. Explicit durations are preserved. It is not forced alignment and is not language-aware syllable counting; the model/token budget can end earlier. +- Three-take mode snapshots the plan, generates independent seeds, and runs one song at a time with both batch sizes set to one. It saves each result before submitting the next. Cancel stops remaining submissions. Reload recovers only the active take; unsubmitted takes are not resumed. +- The Library's Compare takes selector groups candidates; existing playback and favourite controls support choosing a take. No automatic perceptual ranking is claimed. +- Loaded performances and remixes bypass planner overrides. Switching to Library keeps the generation form mounted so the queue remains owned by one component. +- Confirmed terminal job failures/cancellations clear pending recovery; result-download and library-save failures retain it. + +Validation: 15 Node regression tests; clean Svelte check; Vite and native Release builds; isolated Chrome test of controls, persisted profiles, sequential fresh seeds, grouping, cancellation, instrumental preservation and mobile width; temporary CPU server API/embedded-UI smoke checks. Browser generation uses mocked audio. Audible quality and singer consistency have not been established by these tests. + +Build: `npm run build` in tools/webui, then build yue-server. `build/build-producer.cjs` normalizes duplicate Windows PATH keys and creates the Release-producer candidate. `build/activate-producer.ps1` backs up the current Release-reference executable and GGML DLLs, installs the candidate at the existing launcher path, and rolls back on startup failure. diff --git a/docs/app-audit-2026-09-27.md b/docs/app-audit-2026-09-27.md new file mode 100644 index 0000000..f37663b --- /dev/null +++ b/docs/app-audit-2026-09-27.md @@ -0,0 +1,200 @@ +> Current implementation, acceptance evidence and build/recovery instructions: [Studio release guide]( studio-release.md ). This document records earlier planning or audit findings. + +# YuE2 Studio audit — 27 September 2026 + +## Repair update + +Items 1–6 have since been implemented and regression checked. See [reliability repairs](reliability-repairs-2026-09-27.md) for the changes, evidence and limits. The findings below preserve the original audit baseline; items 7–20 remain outstanding unless explicitly noted in that repair report. + +## Assessment + +The app has functioning music generation, planning/voices, lyric assistance, saved tracks, original/master comparison, artwork integration, MP4 export and substantial UI polish. It is not yet a fully resilient production workflow. The most important remaining work is saving and recovering work safely, coordinating long operations, and completing the partially implemented publishing/album workflows. + +This audit changed no application source or production data and restarted no live service. It added this report and disposable audit fixtures under `build/`. + +## Evidence and limits + +- Live YuE2 health passed on port 8087, PID 24296, `build/Release-reference/yue-server.exe`. +- ComfyUI responded on 8188; queue was empty and required Qwen image nodes were present. This proves readiness, not image quality or successful inference. No recent history entries were returned by the history probe. +- Ollama responded; both Tiger-Gemma names were installed. No model was resident at the time of the audit, which is compatible with the lyric code's `keep_alive: 0` behavior. +- Svelte check: **0 errors, 0 warnings**. +- Existing frontend unit suites: **18 passed**. YouTube draft validation: **3 passed**. +- Separate CPU server smoke checks passed: defaults, six invalid requests, oversized request and embedded UI. No songs generated. +- New isolated browser cases reproduced four failures: empty-library navigation, unavailable local storage, invalid saved request and unsuccessful favourite persistence. Output: `build/ui-review/full-audit-findings.json`. +- Previous interaction review covered 244 visible controls with expanded panels/manual mode; six themes, phone width, keyboard interactions and representative operations passed. That was not proof that every backend operation and failure mode worked. +- No real synthesis, image inference, vocal separation or signed-in YouTube upload was performed in this audit. Large-library stress, simultaneous GPU operations, power-loss recovery and dependency vulnerability scanning remain unverified. Remote PR status was not refreshed. + +## Priority 1 — protect work and prevent broken sessions + +### 1. Storage failure or malformed saved settings can prevent the app from rendering + +**Reproduced.** Making the `yue2` local-storage write throw a quota error left the Create heading absent with an uncaught exception. Saving `request.style: 42` caused `style.trim is not a function` and the same failure. + +Evidence: [state.svelte.ts](../tools/webui/src/lib/state.svelte.ts), particularly the unvalidated `parsed.request` at line 38 and unguarded `setItem` at line 120. + +**Needed:** validate/migrate persisted data, catch storage writes, keep the app usable in a clearly indicated unsaved mode, and provide an in-app settings recovery action. Add regression cases for quota, denied storage and malformed field types. + +### 2. MP4 delivery delays saving successfully generated audio + +**Confirmed from code.** `landJob` downloads the audio, then awaits image generation and video rendering; only afterward does it call `putJobSongs`. Ordinary caught failures eventually keep audio, but a browser close/crash plus server restart during those optional stages can lose the finished result before it reaches the library. + +Evidence: [RequestForm.svelte](../tools/webui/src/components/RequestForm.svelte), lines 232–279. + +**Needed:** commit audio immediately, then save artwork/video as separately recoverable updates to the existing track. Show the track as ready for playback while optional delivery work continues. + +### 3. Server job recovery is temporary, not durable + +**Confirmed from code.** Job results live in the process's `g_jobs` map. Completed jobs can be evicted after the 32-job retention limit; restarting discards the map. Browser recovery stores a job ID, not an independent copy of an unfinished/uncollected result. + +Evidence: [yue-server.cpp](../tools/yue-server.cpp), lines 184–244; [db.ts](../tools/webui/src/lib/db.ts), pending-job functions. + +**Needed:** a disk-backed job/result store, startup recovery, retrieval acknowledgement and retention controls. Make the distinction between a server result and a library-saved track visible. + +### 4. Multiple tabs can overwrite or interfere with pending-job recovery + +**Confirmed design gap; race not stress-tested.** All tabs share the single `yue2-job-synth` local-storage key. The check-before-submit sequence is not an atomic lock. Separate tabs can submit before either saves its job ID; a completion can then clear another tab's recovery record. There is no application-wide operation owner or coordinated library refresh. + +Evidence: [RequestForm.svelte](../tools/webui/src/components/RequestForm.svelte), generation loop; [db.ts](../tools/webui/src/lib/db.ts), `saveJob`/`clearJob`. + +**Needed:** per-job records, submission/ownership locking, cross-tab updates and owner-aware cancellation. Test simultaneous starts and reloads. + +### 5. Some library actions show changes before they are safely saved + +**Favourite failure reproduced.** When IndexedDB writes failed, the heart became selected, no error toast appeared and an uncaught exception was raised. Rename, generated-artwork and vocal processing also mutate live song state before the awaited save. Delete handlers have incomplete failure reporting. A long operation can also save a track after the user deleted it because its completion still calls `putSong`. + +Evidence: [SongCard.svelte](../tools/webui/src/components/SongCard.svelte), `toggleFavorite`, `doRename`, `generateArtwork`, `applyVocalBalance`, deletion and asynchronous completion handlers. The rail's favourite handler already uses a safer save-before-display approach. + +**Needed:** shared transactional song updates, visible failure/retry, rollback or save-before-display, and deletion/operation coordination that prevents deleted tracks from reappearing. + +### 6. Backups omit current disk presets and accept insufficiently validated restored data + +**Confirmed from code.** The ZIP includes songs and a fixed list of old browser keys, but not the new `saved_presets` folder. Restore validates little beyond audio Blob, name and truthy request; missing/wrongly typed format/style/request fields can reach components expecting valid strings and objects. The malformed-settings browser test demonstrates why this matters. + +Evidence: [backup.ts](../tools/webui/src/lib/backup.ts), `LOCAL_STORAGE_KEYS`, `exportLibrary`, `importLibrary`; [SongList.svelte](../tools/webui/src/components/SongList.svelte), settings restore. + +**Needed:** versioned full backup schema covering disk presets and current settings; validate everything before replacing the library; offer a pre-restore backup and explain exactly what is included. The normal disposable backup/restore round-trip already passes. + +## Priority 2 — make long workflows and saved outputs consistent + +### 7. Cancel does not cancel the whole MP4 workflow + +**Confirmed from code.** `cancelPipeline` only calls the music job cancellation endpoint and stops remaining takes. Artwork polling has no abort signal, and the video request has no cancellation mechanism. Cancelling after music completes can leave artwork/video continuing while the UI still looks busy. + +Evidence: [RequestForm.svelte](../tools/webui/src/components/RequestForm.svelte):504; [track-artwork.ts](../tools/webui/src/lib/track-artwork.ts); [api.ts](../tools/webui/src/lib/api.ts), `renderVideo`. + +**Needed:** stage-specific cancellation and explicit “stop waiting” versus “cancel owned work” behavior, preserving completed audio and never cancelling unrelated Comfy jobs. + +### 8. Artwork recovery differs between entry points + +**Confirmed from code.** Automatic MP4 generation saves the Comfy prompt ID. On-demand Export video does not persist its artwork job ID. Generate artwork from the track menu keeps its ID only inside the function; closing the dialog stops polling but leaves the Comfy job running. Reload/navigation can therefore orphan an image result from the app's perspective. Some errors refer to resetting an album stage that the song-card UI does not expose. + +Evidence: [track-artwork.ts](../tools/webui/src/lib/track-artwork.ts); [SongCard.svelte](../tools/webui/src/components/SongCard.svelte), `exportVideo` and `generateArtwork`; [comfy-art.ts](../tools/webui/src/lib/comfy-art.ts). + +**Needed:** one persistent artwork operation model, recover completed results by prompt ID, visible retry/reconnect and consistent errors for the actual screen. + +### 9. Existing MP4s and waveforms can become stale after edits + +**Confirmed from code.** Replacing/generating artwork retains the old `song.video`. Vocal adjustment replaces audio but retains both the old video and cached peaks. The waveform reuses `song.peaks` when present, so it can show the previous audio's waveform. The downloaded MP4 can contain an older cover/mix than the current card. + +Evidence: [SongCard.svelte](../tools/webui/src/components/SongCard.svelte):74, 168, 293; [Waveform.svelte](../tools/webui/src/components/Waveform.svelte):88–110. + +**Needed:** invalidate/recompute peaks on audio replacement; record the audio version and artwork revision used in each MP4; mark video outdated and offer a rebuild when inputs change. + +### 10. Expensive services are not coordinated under one scheduler + +**Confirmed architecture gap; resource exhaustion not reproduced.** Native synthesis/transcription use the bounded worker queue. Video and vocal-balance handlers run synchronously outside it. Artwork and Ollama have separate checks. Per-card busy flags do not coordinate other cards, tabs or services; `freeArtworkMemory` is defined but unused. Subprocess waits lack a timeout/cancellation mechanism. + +Evidence: [yue-server.cpp](../tools/yue-server.cpp):867, 919; [audio-video.h](../src/audio-video.h); [audio-vocal-balance.h](../src/audio-vocal-balance.h); [comfy-art.ts](../tools/webui/src/lib/comfy-art.ts). + +**Needed:** bounded operations for video/vocals, shared GPU ownership where appropriate, server-side operation status, subprocess cancellation/timeouts and measured memory handoff between models. Readiness should also check encoder/separator dependencies before a long action starts. + +### 11. “Save preset” still means two different things + +**Confirmed from code.** Named music/lyric blends save into the folder and sidebar. The top-level Save preset button still downloads JSON/YAML and does not save a named full configuration there. A blend does not represent the whole planner/voices/output setup. Blend editors load their lists on mount and do not subscribe to the same preset-change event as the sidebar, so edits in another tab/editor can leave stale choices. + +Evidence: [RequestForm.svelte](../tools/webui/src/components/RequestForm.svelte):309; [BlendFavourites.svelte](../tools/webui/src/components/BlendFavourites.svelte); [SavedPresets.svelte](../tools/webui/src/components/SavedPresets.svelte). + +**Needed:** distinguish named full presets from style blends and file export, unify refresh behavior, and provide a clear naming/save destination flow. + +### 12. Interrupted preset writes lack automatic recovery + +**Confirmed crash window, not power-loss tested.** Existing preset JSON is renamed to `.bak` before `.tmp` is renamed into place. A crash between those operations leaves the preset absent from listing; subsequent saves reject the remaining backup. Rename of a preset is a multi-request save/delete operation and can partially complete. + +Evidence: [saved-presets.h](../src/saved-presets.h), save handler; [BlendFavourites.svelte](../tools/webui/src/components/BlendFavourites.svelte), `commit`. + +**Needed:** startup reconciliation for temporary/backup files and a transactional server rename/update operation with conflict detection. + +### 13. Progress/ETA is not a complete job tracker + +**Confirmed limitation.** The percentage/ETA measures the current NAR chunk, not the whole song. Status is derived from global log text and local tab state, so unrelated jobs and replayed log history can affect interpretation; another tab can show Ready while the server is working. Artwork and video lack measured progress. Remaining planned takes are not resumed after reload. + +Evidence: [activity.svelte.ts](../tools/webui/src/lib/activity.svelte.ts); [LogCard.svelte](../tools/webui/src/components/LogCard.svelte); RequestForm's take loop. + +**Needed:** job-scoped structured stage events, queue position, stage-specific estimates and a persisted take queue. Continue labelling estimates honestly until enough measurements exist. + +### 14. Navigation has hidden-target and duplicate-panel problems + +**Empty-library link reproduced.** “Shape your first track” changes the hash but leaves Library visible and Create hidden. Create remains mounted with `display:none` while Library adds another StudioRail; this also duplicates the settings target and log subscription. Settings links can target the hidden copy, and preview playback can continue from the hidden Create view. + +Evidence: [SongList.svelte](../tools/webui/src/components/SongList.svelte):77; [App.svelte](../tools/webui/src/App.svelte):126 and library rail; [StudioRail.svelte](../tools/webui/src/components/StudioRail.svelte). + +**Needed:** centralized view navigation, unique section IDs, intentional playback behavior on view changes and one shared activity subscription. + +### 15. Invalid audio fails silently + +**Confirmed from code.** Audio import saves a file based on its extension without first validating decode. Waveform decoding catches and discards errors. A broken/unsupported file can become a nonworking card without a useful explanation; Play can appear selected despite no decoded audio. + +Evidence: RequestForm `openAudio`; [Waveform.svelte](../tools/webui/src/components/Waveform.svelte):110. + +**Needed:** validate imports, show decoding/loading/error states, disable playback when unavailable and provide a retry/remove route. + +### 16. Large-library memory use needs measurement and limits + +**Confirmed eager-loading design; stress impact unmeasured.** The app gets all songs, mounts every visible song waveform and decodes full audio buffers. Library cards and preview can decode the same song separately. Job retention is bounded by count rather than bytes, and results include originals/masters. Video export reads the finished MP4 fully into memory. + +Evidence: [db.ts](../tools/webui/src/lib/db.ts), `getAllSongs`; SongList's full list; Waveform's decoding effect; server job retention; audio-video output loading. + +**Needed:** benchmark realistic libraries, lazy/shared audio decoding, list virtualization or pagination, byte-based retention and streamed/limited media handling where practical. + +## Priority 3 — finish promised workflows and make releases repeatable + +### 17. YouTube remains an assisted first version + +**Confirmed implementation status.** Local draft editing/export and basic browser automation exist. Playlist, end screens, disclosures, scheduling and final save/publish remain manual. The UI requires downloading files and running a terminal command. The runner explicitly says a user-reviewed run is not verified publication; signed-in upload automation has not been exercised in the available evidence. + +Evidence: [agent.mjs](../tools/youtube-agent/agent.mjs), [README](../tools/youtube-agent/README.md), [YouTubeDialog.svelte](../tools/webui/src/components/YouTubeDialog.svelte). + +**Needed:** agree the remaining automation scope, test against a dedicated upload draft, handle changed/localized Studio selectors, resume existing uploads safely, and expose a clearer launch/status path. Keep publishing an explicit user action unless separately authorized. + +### 18. Album creation is scaffolded, not a delivered workflow + +**Confirmed from imports and UI.** Album types, database and planning helpers exist. No connected album runner/workspace completes the roadmap for a resumable track queue, master cover and distinct referenced track artwork. + +Evidence: `album-types.ts`, `album-db.ts`, `album-plan.ts`; current App/RequestForm component tree. + +**Needed:** implement the persisted album state machine, queue/resume controls, per-track retry, shared cover/reference workflow and export. Treat this as a feature project after reliability work, not a small UI addition. + +### 19. Real media quality and adverse-condition tests remain incomplete + +**Verification gap.** Unit/UI checks do not establish actual lyric quality, requested voice behavior, reference-image consistency, vocal separation quality, measured final loudness/true peak, long-track MP4 compatibility or recovery under resource exhaustion. Streaming/Broadcast are real FFmpeg loudness-normalization profiles, not a full creative mastering chain. Original/master pairing has three passing regression cases, so the previously reported duplicate-card issue has a targeted fix and coverage. + +**Needed:** a documented media acceptance matrix with short real generation runs, multi-take runs, original/master measurements, actual generated artwork, reference edit, vocal balance, MP4 playback and interrupted-run recovery. Record which combinations were actually tested and the hardware/memory costs. + +### 20. Current work is not packaged as a reproducible reviewed release + +**Confirmed repository state.** There are 24 modified tracked files plus substantial untracked implementation/documentation. The running build includes work outside the last commit. Current interaction/theme audit scripts are under ignored `build/`; PR CI does not run the Svelte checks or these UI tests. Older audit/resume documents still describe already delivered artwork/MP4 features as unfinished and contain outdated launcher/deployment details. + +Evidence: local Git status; [CI workflow](../.github/workflows/ci-build.yml); `AUDIT_REPAIRS.md`; `PROJECT_BUILD_PLAN.md`; `build/interaction-review.mjs` and related scripts. + +**Needed:** curate persistent tests into the repository, add frontend checks/tests to CI, document one authoritative build/deploy/recovery route, refresh the status documentation, and make a reviewed commit/PR update. Do not include user media, model files, private browser profiles or temporary logs. Commit/push was not performed by this audit. + +## Recommended execution order + +1. **Prevent lost work:** findings 1–6. Pass quota, restart, multi-tab and full backup/restore scenarios before calling recovery reliable. +2. **Make long operations consistent:** findings 7–13. Save audio first; make artwork/video cancellable, resumable and revision-aware. +3. **Complete the everyday UI:** findings 14–16 and the preset workflow in 11. Fix navigation and playback errors, then measure large libraries. +4. **Run real media acceptance checks:** finding 19. Separate measured passes from model-dependent expectations. +5. **Package the release:** finding 20. Keep regression tests and current operations documentation with the source. +6. **Finish feature projects:** YouTube and albums (17–18) after their recovery foundations are in place. + +No fixes were applied as part of this audit; the findings above remain open unless explicitly described as already covered/passing. diff --git a/docs/interaction-plan.md b/docs/interaction-plan.md new file mode 100644 index 0000000..6230f7b --- /dev/null +++ b/docs/interaction-plan.md @@ -0,0 +1,47 @@ +# Studio interaction plan + +Every control receives theme-aware hover, keyboard focus, pressed and disabled states. Hover takes 140 ms; press takes 90 ms. Motion is disabled when reduced motion is requested. Cards emphasize their border without moving their contents. Only actionable controls lift; destructive actions retain a distinct warning color. No click sounds, fake progress or idle pulsing. + +## Component inventory and treatment + +| Area | Cards and controls | Planned response | +| --- | --- | --- | +| App shell | Navigation, theme selector, volume, connection | Active navigation stays selected; keyboard focus remains visible; volume updates immediately; connection reflects actual state. | +| Saved presets | Preset cards, empty state | Hover/focus emphasis, pressed feedback, loaded confirmation; keep names readable. | +| Workflow | Sound, planner, lyrics, generate navigation | Active step uses accent; hover previews action without moving panels. | +| Sound | Style tiles, add/remove, search, category controls | Image emphasis on hover; selected border/check remain visible; search gets focus ring. | +| Blend controls | Influence dials and numeric inputs | Drag state and grabbing cursor; arrows and numeric edits retained; distinct focus. | +| Saved blends | Choose, load, name, save, update, rename, delete | Disable conflicting actions while writing; visible saving status; load confirmation; preserve destructive confirmations. | +| Planner | Voice selectors, layout, length, structure and automatic options | Consistent field focus and pressed states; disabled automatic controls stay visibly unavailable. | +| Lyrics | Styles, assistant, prompt, text editor, generate/cancel | Selection confirmation; text remains stable while editing; real busy text and cancellation retained. | +| Composition | Melody/reference selection, range, upload/reset | Clear action and disabled states; range controls remain available for precise keyboard editing. | +| Engine | Model choices and advanced disclosure | Distinct focus, open disclosure styling and selected states. | +| Sampling | Range/number pairs, reset and automatic settings | Range hover/focus response; paired values unchanged; disabled controls do not animate. | +| Output | Format, mastering, monitor volume | Consistent focus; dropdown choices remain native and accessible. | +| Generation | Generate/queue/cancel and progress | Primary button has stronger emphasis; existing real progress/ETA retained; busy feedback does not imply completion. | +| Library | Search, favourites, backup, restore, empty state | Active filter indication; visible operation name while backup/restore runs; prevent duplicate operations. | +| Track cards | Play/stop, remix, favourite, version comparison | Playing border, pressed playback state, favourite pop, persistent selected version. | +| Track menu | Download, video export, artwork, transcription, vocal balance, rename, delete, YouTube | Keyboard arrow/Home/End navigation; Escape restores trigger; busy operations guarded and labelled; deletion distinct. | +| Artwork | Cover, fullscreen, close, prompt, seed/dice, generate | Cover affordance; existing fullscreen dismissal; visible rendering state and disabled concurrent inputs. | +| Waveform | Seek and range selection | Keyboard seek with arrows/Home/End and Space playback; visible focus; pointer cancellation clears dragging. | +| Preview rail | Cover, transport, recent tracks and favourites | Same control language as library; active playback and selected tracks remain distinct. | +| Activity | Disclosure, progress, log viewport | Open/focus emphasis; existing stage colors and real progress retained; no decorative fake progress. | +| Dialogs | Rename/delete and custom action dialogs | Initial focus, Tab containment, Escape dismissal and return focus; multiline Enter never accidentally confirms. | +| YouTube | Metadata, checkboxes, save/export draft and cancel | Shared button/input feedback; existing saved/busy/error state retained; publishing remains explicit. | +| Toasts | Success and error notices | Distinct icons and colors, theme-readable surface and polite announcement. | +| Visualizer | Playback-driven canvas | Keep existing audio response and reduced-motion behavior; do not add idle animation. | + +## Review boundaries + +Inspect each component and shared controls. Build/typecheck the UI, then exercise navigation, keyboard menus/dialogs, style selection, presets, playback and busy/error states in an isolated browser profile. Review all six themes and reduced motion. Use mocked operations for destructive/server-heavy actions; do not generate songs, delete real tracks or publish uploads as part of interaction review. + +## Execution record — 27 September 2026 + +- Implemented shared hover/press/focus/disabled feedback and component-specific selection, playback, drag, busy, success and error feedback. +- Reviewed 244 visible controls with panels expanded and manual settings enabled; keyboard focus checked for every enabled control in that inventory. +- Browser exercises passed for named preset saving/loading, style selection, manual sampling, menu arrows/Home/End/Escape, dialog initial focus/Tab containment/return focus, favourites, waveform seeking/playback, artwork dismissal, transcription busy/error and YouTube draft saving. +- All six themes passed desktop and 390-pixel phone width checks. Secondary text palette contrast ranged from 5.93:1 to 8.41:1. Screenshot review additionally caught and corrected library title/play-control contrast in Studio Glass. +- Reduced-motion checks passed. UI typecheck: zero errors and zero warnings. Frontend and embedded server builds completed; native build retains an existing numeric-conversion warning in sheetsage.h. +- Review uses a disposable browser library and mocked server mutations. These checks cover interaction behavior, not the quality of newly generated audio/artwork or actual YouTube publication. +- Local review artifacts: `build/ui-review/control-inventory.json`, `interaction-library.png`, `theme-*.png`, and `glass-mobile.png`. +- Additional disposable-library checks passed for renaming, audio download and backup/restore. Active generation was cancelled at the user's request and the rebuilt server activated on port 8087. diff --git a/docs/lyric-style-pack/README.md b/docs/lyric-style-pack/README.md new file mode 100644 index 0000000..71bcbd8 --- /dev/null +++ b/docs/lyric-style-pack/README.md @@ -0,0 +1,78 @@ +# HipHop Lyric Style Pack + +This pack contains 30 lyric-generation style profiles for a HipHop music-generation app. + +Each `.md` file is designed as an instruction module, not just a style description. The files define: +- cadence and speed +- syllable targets +- rhyme density +- internal and multisyllabic rhyme behavior +- punchline frequency +- wordplay and metaphor level +- storytelling intensity +- aggression and emotion +- preferred rhyme structures +- mandatory writing rules +- failure conditions +- self-check rules +- behavior when styles are combined + +## Recommended App Behavior + +1. Load the selected style file into the lyric-generation system prompt or style context. +2. Treat **Mandatory Writing Rules** as hard constraints. +3. Generate a first draft. +4. Run the draft against the **Style Compliance Check**. +5. Rewrite failed sections automatically. +6. Return only the corrected version to the user. + +## Style Mixing + +Recommended UI: +- Primary Style: 60–100% influence +- Secondary Style: 0–50% influence +- Optional Modifier: 0–30% influence + +The primary style should always retain its defining flow and rhyme behavior. + +## Included Styles + +1. Fast Punchy +2. Syllable Dense +3. Machine Gun Flow +4. Battle Rap +5. Street Grit +6. Boom Bap Classic +7. Underground Abstract +8. Chilled Flow +9. Smooth Storyteller +10. Punchline Heavy +11. Wordplay Technician +12. Internal Rhyme Heavy +13. Multisyllabic Master +14. Flow Switcher +15. Staccato Rap +16. Run-On Flow +17. Dark Cinematic +18. Introspective +19. Conscious Rap +20. Braggadocious +21. Minimalist Menace +22. Chaotic Energy +23. Melodic Rap +24. Hook Driven +25. Freestyle Feel +26. Complex Schemes +27. Double-Time Technical +28. Slow Heavy Bars +29. Psychedelic Rap +30. Experimental Flow + +## Implementation Note + +For best results, do not ask the model to merely "write like [style]." +Instead, inject the complete selected `.md` profile and instruct the model to validate the result before returning it. + +Suggested final system directive: + +> Follow the active lyric-style profile as a hard constraint. Generate the requested lyrics, silently evaluate them against every mandatory rule and compliance item, rewrite anything that fails, and return only the final compliant lyrics. diff --git a/docs/lyric-style-pack/_STYLE_SCHEMA.md b/docs/lyric-style-pack/_STYLE_SCHEMA.md new file mode 100644 index 0000000..b6307a0 --- /dev/null +++ b/docs/lyric-style-pack/_STYLE_SCHEMA.md @@ -0,0 +1,54 @@ +# Lyric Style File Schema + +Use this format when adding future styles. + +```md +# Style Name + +## Purpose +One-sentence definition of the intended lyrical behavior. + +## Style Lock +Instruction that the generator must enforce the style structurally. + +## Core Profile +- Energy +- Delivery Speed +- Target Syllables +- Rhyme Density +- Internal Rhyme Density +- Multisyllabic Rhyme Level +- Punchline Frequency +- Wordplay Level +- Metaphor Density +- Vocabulary +- Storytelling Level +- Aggression +- Emotional Intensity +- Repetition +- Flow Variation +- Preferred Rhyme Schemes +- Bar Structure +- Hook Compatibility + +## Mandatory Writing Rules +Concrete rules the model must satisfy. + +## Avoid +Style-breaking behavior. + +## Generation Procedure +Drafting and revision procedure. + +## Style Compliance Check +Binary self-checks. + +## Failure Conditions +Conditions that force regeneration. + +## App Instruction +How the app should enforce the preset. + +## Combination Behavior +How this style behaves when mixed with another. +``` diff --git a/docs/reliability-repairs-2026-09-27.md b/docs/reliability-repairs-2026-09-27.md new file mode 100644 index 0000000..cc9eec8 --- /dev/null +++ b/docs/reliability-repairs-2026-09-27.md @@ -0,0 +1,33 @@ +# Reliability repairs — 27 September 2026 + +Implements audit items 1–6. All previous working-tree changes are preserved; nothing has been committed or pushed. + +## Changes + +1. Settings are validated on load. Storage failures leave the interface usable with a visible warning and a save-again action. +2. Generated audio is committed to the library before optional artwork and MP4 processing. Later results update the existing song. +3. The server archives completed job results in `job_results/`. A restart can retrieve completed results; interrupted inference is explicitly reported and must be restarted. Acknowledged results become eligible for cleanup after 30 days; unacknowledged results are retained. Cleanup runs on acknowledgement. +4. Pending jobs live in IndexedDB, with client-generated submission IDs and a browser-wide operation lock. Retrying the same submission returns the same job. Other tabs receive library-change notifications. +5. Track edits use transactional patches and update the visible state after a successful save. Late processing cannot recreate a deleted song. Replacing audio or artwork invalidates dependent cached media. +6. Backup version 2 includes disk presets and current settings. Restore validates data before changing the library, downloads a before-restore backup, merges presets without overwriting conflicts, and replaces songs atomically. + +## Verification + +- Svelte check: 0 errors and 0 warnings. +- Frontend unit suites: 22 passed, including malformed requests, song/preset validation and backup roundtrip. +- Isolated browser storage checks passed: quota failures, malformed settings, recovery record before submission, two-tab submission, audio saved before artwork, failed favourite save, deletion during optional processing. +- Interaction review passed: 244 visible controls, keyboard navigation, dialogs, presets, playback, artwork preview, error feedback, YouTube draft save, rename, downloads, backup/restore, reduced motion and phone layout. +- Native archive tests passed: binary persistence, metadata-only reads, interrupted state, idempotence, acknowledgement retention and safe IDs. +- Isolated HTTP restart check passed across two server starts. No synthesis was performed by that test. +- UI and native builds completed. Native compilation retains the existing SheetSage numeric-conversion warning. +- Final candidate CPU smoke checks passed, including invalid/oversized requests and embedded UI. +- Activated on port 8087, PID 15944. Live health passed and served UI bytes exactly match the final bundle. Previous binaries are preserved in `build/backup-before-producer-20260927-144608/`. + +## Limits and remaining work + +- These checks use disposable browser libraries and mocked media operations. Fresh real music, image inference and signed-in YouTube publishing were not exercised. +- In-flight model computation cannot resume after a restart. Results already lost by an older server cannot be recovered retroactively. Power-loss durability has not been tested. +- Browser library storage is still local to its browser profile; backups remain necessary. +- Preset files, IndexedDB and browser settings cannot be committed in one transaction. If restore fails partway, successfully imported presets remain; existing presets are preserved and the before-restore backup provides a recovery path. +- Archive retention is currently a fixed policy, not a settings control. +- Audit items 7–20 remain for subsequent work. Dependent media invalidation partially addresses item 9; full operation cancellation, GPU scheduling, publishing, album flows, performance and real media acceptance checks remain outstanding. diff --git a/docs/studio-release.md b/docs/studio-release.md new file mode 100644 index 0000000..c05f0d8 --- /dev/null +++ b/docs/studio-release.md @@ -0,0 +1,86 @@ +# Studio implementation and release — 27 September 2026 + +This is the current operations guide. `app-audit-2026-09-27.md` records the original findings; the older roadmap documents are historical. + +## Implemented + +| Audit items | Delivery | +| --- | --- | +| 1–6 | Validated settings/backups, audio-first saving, durable server results, per-job browser recovery, cross-tab ownership, transactional song updates. | +| 7–9 | Owned video cancellation; artwork stop-waiting/reconnect; persistent job IDs; media revisions reject stale completions and invalidate old MP4s/waveforms. | +| 10 | Bounded native queue for music/transcription/video/vocals; GPU admission gate for native jobs, Comfy submissions and Ollama; cancellable subprocesses with 30-minute deadline; dependency checks. | +| 11–12 | Named full Studio presets plus style blends in `saved_presets`; separate request-file export; atomic rename, interrupted-write recovery and cross-tab refresh. | +| 13 | Server job/stage/queue status, measured stage progress and persisted planned takes. ETA remains unavailable for stages without sufficient measurements. | +| 14–16 | Central navigation; single active rail; visible audio errors; lazy/shared decoding, 96 MiB decode cache and 12-card pages; disk-backed completed results; 256 MiB MP4 output cap. Recovery admission stops above 16 GiB or below 512 MiB free disk without deleting unacknowledged results. | +| 17 | Integrated YouTube launch/status/reconnect and local metadata drafts. **User deferred the upload check. Nothing uploaded or published.** Playlist and publishing remain user actions. Signed-in acceptance is incomplete. | +| 18 | Persisted album queue, reload/resume, stage retry, master/reference artwork, per-track video and album/backup ZIP export. | +| 19 | Real media acceptance recorded below; model quality is reviewed separately from successful execution. | +| 20 | Persistent test scripts, frontend CI, build/deployment wrappers and this guide. Commit/PR status is reported with the release. | + +## Build and deploy on this Windows installation + +Prerequisites: Visual Studio C++ build tools, CMake, CUDA toolkit, Node, FFmpeg on PATH, installed YuE2/VAE/SheetSage model files. Existing configured build directory is reused. + +```powershell +cd tools/webui +npm ci +npm run check +npm run build +cd ../.. +node tools/build-studio.mjs +node tools/activate-studio.mjs +``` + +For a fresh CUDA configuration, initialize the ggml submodule and run `cmake -S . -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=89` before building on the RTX 4060. Use the architecture appropriate to other hardware. + +The build writes `build/Release-producer`. Activation refuses active native jobs, backs up the previous binaries under `build/backup-before-producer-*`, stops the matching server, deploys into `build/Release-reference`, starts hidden on 8087 and checks health. On startup failure it restores the backup. The Node wrapper normalizes Windows environment-key casing before calling PowerShell. + +Use `GET /health`, `/jobs` and `/capabilities` for readiness. Logs are `build/producer-server.err.log` and `.out.log`. A browser refresh loads the embedded UI. The browser library is IndexedDB tied to the browser profile and origin; keep using the same `http://localhost:8087` origin. + +## Optional services + +- ComfyUI: managed Pinokio app `inteliweb-comfyui`, loopback 8188. Qwen Image 2.1 Q4_K_M, Qwen3-VL 8B INT8 and matching VAE are required. Use Pinokio/pterm for its lifecycle. +- Some GGUF loader versions do not recognize metadata-free Qwen 2.1 files. `node tools/repair-comfy-gguf.mjs ` adds a narrowly matched architecture signature and keeps a `.before-yue2-qwen21` backup. Restart Comfy through Pinokio after this repair. It was needed on this installation. +- Ollama: loopback 11434; the browser uses the native `/ollama` bridge for resource coordination. Installed model selection is discovered, not hardcoded. +- Vocal separation: run `./setup-vocal-separation.ps1`. This creates isolated `.venv-vocal`, installs the separator and CUDA PyTorch, and checks the environment. The separation model downloads on first use into the OS temporary model directory. Restart Studio after setup so its PATH includes the environment. +- YouTube: `npm ci` in `tools/youtube-agent`. The integrated bridge opens a separate Chrome profile; it cannot attach to an ordinary signed-in Chrome window. The upload check is deferred at the user's request. Private profiles and run media are ignored by Git. + +## Recovery and backup + +- Completed audio is saved before optional art/video. If either optional stage fails, use the song card's reconnect/retry controls. +- Stopping artwork waiting preserves the Comfy prompt ID; it does not interrupt another application's GPU job. +- On native restart, completed results remain retrievable; in-flight native computation is marked interrupted and must be retried. +- Do not remove `job_results` before confirming library backups. Unacknowledged results are retained. Acknowledged results expire after 30 days. +- Library backup includes songs, current settings, disk presets and album plans/covers. Restore validates before mutation, downloads a before-restore ZIP and merges conflicting preset names safely. Album song IDs are remapped after restore. +- Album Pause finishes and saves the current stage. Resume skips saved stages and reuses persisted server/Comfy IDs. + +## Acceptance evidence + +Persistent commands: + +```powershell +node --experimental-strip-types --test tools/webui/tests/*.test.mjs +node tests/studio-interactions.mjs +node tests/workflow-browser.mjs +node tools/webui/tests/storage-browser.mjs +node tests/media-queue.mjs +node tests/recovery-http.mjs +``` + +The browser suites use disposable contexts and mocked service responses. They do not upload to YouTube or modify the user's browser library. + +- 24 unit tests passed, including original/master pairing, remix identity, input validation and backup validation. +- 245 controls inventoried/focused; keyboard dialogs/menus, save/load, playback, export, failures, mobile layout and reduced motion passed. +- Quota failure, malformed settings, two-tab submission, audio-first saving, failed favourite rollback and no deleted-track resurrection passed. +- Two-track album reload/resume reused the first job ID and created two tracks. A 122-track library mounted 12 cards with zero eager audio decodes when peaks existed. Measured JavaScript used heap was about 10 MB for this short-audio fixture; this does not measure total browser Blob/native audio memory for long tracks. +- Native async MP4, idempotent retry, cancellation, interrupted preset recovery and atomic rename passed. +- RTX 4060 Laptop 8 GiB: two 12-second real takes plus originals completed in about 16.2 seconds. WAV: 48 kHz stereo, 24-bit. Streaming master measured −15.93 LUFS and −1.54 dBTP on the short sample; the profile target is not a promise of an exact measured value for every clip. +- Actual Qwen cover generation passed, about 152 seconds at 1024 square. The first reference result copied the scene too closely. Increasing reference guidance to 4 produced a distinct rooftop/drum-machine scene with the same amber/purple palette; visual review passed (506 seconds). +- Six-minute MP4 acceptance passed: H.264 1920×1080 + AAC, 360-second video/audio duration, idempotent retry and cancellation. The check found and fixed FFmpeg lookahead leaving a silent tail at 1 fps; exports now use the decoded audio duration explicitly. +- Real Tiger-Gemma lyric generation passed through the native Ollama bridge on CPU in 22 seconds. Ollama's CUDA runner failed initialization on this installation; the lyric assistant now retries that failure once on CPU with a visible notice. Existing lyrics remain intact on errors, and models unload after completion. +- Dependency audit fixes stayed within the declared compatible ranges; npm reports zero vulnerabilities after 11 package updates. Svelte checks remained at zero errors/warnings. +- Real generated artwork and music were combined into `build/media-acceptance/hiphop-circuit-test.mp4`. Artifacts, raw measurements and subsequent checks remain under ignored `build/media-acceptance`. +- Real GPU vocal separation and +3 dB remix passed in 12.2 seconds after fixing Windows argv quoting and resampling before sample-accurate trimming. The output retained the source sample count and rate. Model weights are now cached locally. +- Reference and vocal evidence are recorded in `followup.json`; execution success does not establish subjective vocal quality, lyric intelligibility or every requested voice characteristic. + +Do not treat the mocked browser tests as signed-in YouTube acceptance, or the short media fixture as a full-duration quality guarantee. diff --git a/lyric_styles/00_STYLE_INDEX.yaml b/lyric_styles/00_STYLE_INDEX.yaml new file mode 100644 index 0000000..e79fa76 --- /dev/null +++ b/lyric_styles/00_STYLE_INDEX.yaml @@ -0,0 +1,12 @@ +version: "1.0" +styles: + - {id: rapid_fire, name: Rapid-Fire Momentum, filename: 01_rapid_fire.yaml, description: Fast phonetic momentum with clear meaning, primary_strength: velocity, syllable_density: 0.82, complexity: 0.72, energy: 0.92, best_for: [rap, electronic, drum_and_bass], contrast: dense rhythm and short units} + - {id: syllable_dense, name: Technical Rhyme Architecture, filename: 02_syllable_dense.yaml, description: Interlocking multisyllabic rhyme systems, primary_strength: technicality, syllable_density: 0.96, complexity: 0.96, energy: 0.74, best_for: [rap, boom_bap, experimental], contrast: maximum internal structure} + - {id: chilled_conversational, name: Chilled Conversational Flow, filename: 03_chilled_conversational.yaml, description: Natural speech with understated rhyme, primary_strength: effortless authenticity, syllable_density: 0.42, complexity: 0.48, energy: 0.38, best_for: [hip_hop, lo_fi, pop], contrast: breathing room and loose placement} + - {id: punchline, name: Bar-Heavy Punchline Craft, filename: 04_punchline.yaml, description: Compact setups and intelligent payoffs, primary_strength: quotability, syllable_density: 0.68, complexity: 0.78, energy: 0.76, best_for: [rap, boom_bap, grime], contrast: one strong idea per bar pair} + - {id: cinematic_story, name: Cinematic Storytelling, filename: 05_cinematic_story.yaml, description: Scene-led narrative with callbacks and consequence, primary_strength: narrative immersion, syllable_density: 0.54, complexity: 0.82, energy: 0.62, best_for: [soundtrack, rap, folk], contrast: plot progression over display} + - {id: melodic_emotional, name: Melodic Emotional Anchors, filename: 06_melodic_emotional.yaml, description: Singable emotional phrases with meaningful detail, primary_strength: hookability, syllable_density: 0.48, complexity: 0.62, energy: 0.58, best_for: [pop, rnb, melodic_rap], contrast: vowel-friendly anchors and controlled repetition} + - {id: raw_direct, name: Raw Direct Precision, filename: 07_raw_direct.yaml, description: Concrete forceful language without ornament, primary_strength: impact, syllable_density: 0.46, complexity: 0.44, energy: 0.82, best_for: [rap, punk, rock], contrast: literal observation and strong verbs} + - {id: abstract_psychedelic, name: Abstract Dream Logic, filename: 08_abstract_psychedelic.yaml, description: Surreal connected imagery with emotional logic, primary_strength: originality, syllable_density: 0.58, complexity: 0.88, energy: 0.64, best_for: [experimental, electronic, art_pop], contrast: unusual associations with thematic coherence} + - {id: minimalist_space, name: Minimal Space-Driven Writing, filename: 09_minimalist_space.yaml, description: Few high-value words and intentional silence, primary_strength: memorability, syllable_density: 0.22, complexity: 0.38, energy: 0.34, best_for: [ambient, trap, indie], contrast: space is part of the composition} + - {id: progressive_switching, name: Progressive Flow Switching, filename: 10_progressive_switching.yaml, description: "Purposeful changes in cadence, density and perspective", primary_strength: evolution, syllable_density: 0.76, complexity: 0.91, energy: 0.78, best_for: [progressive_rap, fusion, electronic], contrast: structured transformation across sections} diff --git a/lyric_styles/01_rapid_fire.yaml b/lyric_styles/01_rapid_fire.yaml new file mode 100644 index 0000000..1fa1830 --- /dev/null +++ b/lyric_styles/01_rapid_fire.yaml @@ -0,0 +1,13 @@ +style: {id: rapid_fire, name: Rapid-Fire Momentum, version: "1.0", category: rhythm_engine, description: Fast phonetic momentum without sacrificing semantic clarity} +identity: {core_philosophy: Every bar should propel the next, listener_impression: breathless controlled momentum, primary_strengths: [velocity, cadence, internal_rhyme], intentionally_avoids: [empty filler, unreadable speed, identical bar shapes]} +rhythm: {pace: fast, syllable_density: 0.82, average_syllables_per_bar: 15, line_length: short_to_medium, rhythmic_subdivision: frequent eighths_and_sixteenths, cadence_character: clipped_chained, syncopation: 0.78, pause_usage: strategic_breath_points, enjambment: 0.68, flow_variation: 0.62, flow_switch_frequency: 0.35} +rhyme: {overall_density: 0.82, end_rhyme_frequency: 0.62, internal_rhyme_frequency: 0.88, multisyllabic_rhyme_level: 0.68, rhyme_chain_length: 3, slant_rhyme_usage: 0.55, consonance: 0.72, assonance: 0.68, rhyme_resolution: delayed, rhyme_predictability: 0.35} +language: {vocabulary_complexity: 0.62, sentence_complexity: 0.58, conversational_level: 0.42, metaphor_density: 0.48, wordplay_density: 0.62, imagery_density: 0.58, abstraction_level: 0.38, directness: 0.62, profanity_behavior: contextual, filler_tolerance: 0.08} +delivery: {perceived_energy: 0.92, aggression: 0.58, smoothness: 0.48, emotional_intensity: 0.62, vocal_space: 0.2, breath_demand: 0.9, emphasis_behavior: accented_rhythmically} +composition: {verse_behavior: escalating_chained_bars, hook_behavior: simpler_reset, bridge_behavior: brief_breath_or_contrast, opening_behavior: immediate_motion, closing_behavior: clean_final_rhyme, repetition_level: 0.28, callback_usage: 0.42, progression_style: acceleration_then_release} +storytelling: {narrative_priority: 0.42, perspective: flexible, scene_detail: 0.48, continuity: 0.62, character_usage: optional, temporal_progression: linear_or_associative, payoff_behavior: final_bar_resolution} +technical_rules: {hard_rules: ["Keep meaning clear at speed", "Use frequent internal rhyme or rhythmic echo", "Create intentional breath points", "Do not pad lines to hit syllable count"], preferred_rules: ["Chain 2-4 related sounds", "Use consonants that articulate quickly", "Vary line endings"], optional_behaviors: ["Short burst of double-time", "One deliberately sparse reset"]} +anti_patterns: {never_do: ["nonsense filler", "constant perfect couplets", "unreadable tongue-twisters"], avoid_overusing: ["same vowel family", "identical 16-syllable lines"], warning_signs: ["meaning disappears when read aloud"]} +generation_guidance: {planning_method: map_topic_to_three_motifs_then_build_sound_chains, writing_order: meaning_then_rhythm_then_rhyme, revision_method: remove_filler_and_test_breaths, quality_checks: [clarity, breathability, sound_variety, no_recycled_phrases]} +adaptation: {works_best_with: [rap, electronic, drum_and_bass], can_adapt_to: [pop, rock, spoken_word], topic_handling: concrete_motifs, emotional_range: medium_to_high} +metrics: {syllable_density: 0.82, rhyme_density: 0.82, internal_rhyme: 0.88, melodic_bias: 0.2, narrative_bias: 0.42, abstraction: 0.38, aggression: 0.58, repetition: 0.28, flow_variability: 0.62, punchline_bias: 0.45, imagery: 0.58, directness: 0.62, emotional_intensity: 0.62, space: 0.2, breath_demand: 0.9} diff --git a/lyric_styles/02_syllable_dense.yaml b/lyric_styles/02_syllable_dense.yaml new file mode 100644 index 0000000..ef152cd --- /dev/null +++ b/lyric_styles/02_syllable_dense.yaml @@ -0,0 +1,13 @@ +style: {id: syllable_dense, name: Technical Rhyme Architecture, version: "1.0", category: language_engine, description: Interlocking multisyllabic rhyme systems that remain semantically coherent} +identity: {core_philosophy: Build a connected lattice of sound and meaning, listener_impression: intricate and rewarding, primary_strengths: [multisyllabic_rhyme, internal_structure, wordplay], intentionally_avoids: [random_thesaurus_words, empty complexity, forced grammar]} +rhythm: {pace: flexible, syllable_density: 0.96, average_syllables_per_bar: 17, line_length: medium_to_long, rhythmic_subdivision: varied, cadence_character: tightly_interlocked, syncopation: 0.72, pause_usage: deliberate, enjambment: 0.82, flow_variation: 0.66, flow_switch_frequency: 0.42} +rhyme: {overall_density: 0.95, end_rhyme_frequency: 0.58, internal_rhyme_frequency: 0.96, multisyllabic_rhyme_level: 0.96, rhyme_chain_length: 5, slant_rhyme_usage: 0.72, consonance: 0.9, assonance: 0.88, rhyme_resolution: delayed_layered, rhyme_predictability: 0.22} +language: {vocabulary_complexity: 0.84, sentence_complexity: 0.86, conversational_level: 0.38, metaphor_density: 0.62, wordplay_density: 0.9, imagery_density: 0.68, abstraction_level: 0.56, directness: 0.5, profanity_behavior: contextual, filler_tolerance: 0.03} +delivery: {perceived_energy: 0.74, aggression: 0.45, smoothness: 0.42, emotional_intensity: 0.58, vocal_space: 0.24, breath_demand: 0.92, emphasis_behavior: emphasize_rhyme_turns} +composition: {verse_behavior: evolving_rhyme_families, hook_behavior: contrast_and_simplify, bridge_behavior: reveal_new_sound_family, opening_behavior: establish_concept_and_rhyme, closing_behavior: resolve_or_reframe, repetition_level: 0.2, callback_usage: 0.62, progression_style: increasing_interconnection} +storytelling: {narrative_priority: 0.5, perspective: flexible, scene_detail: 0.55, continuity: 0.68, character_usage: optional, temporal_progression: flexible, payoff_behavior: conceptual_reveal} +technical_rules: {hard_rules: ["Every complex phrase must serve meaning", "Use at least two internal sound relationships per bar on average", "Build rhyme chains rather than isolated rhymes", "Preserve grammatical readability"], preferred_rules: ["Use multisyllabic slant rhyme", "Layer consonance under vowel rhyme", "Let sentences cross bar lines"], optional_behaviors: ["Nested double meaning", "Rhyme family mutation in final section"]} +anti_patterns: {never_do: ["random ornate vocabulary", "rhymes that distort the subject", "unbroken rhyme monotony"], avoid_overusing: ["perfect rhyme", "same sentence length"], warning_signs: ["a line sounds impressive but says nothing"]} +generation_guidance: {planning_method: define_subject_thesis_then_three_rhyme_families, writing_order: semantic_map_then_sound_lattice_then_revision, revision_method: delete_any_sound_without_semantic_job, quality_checks: [coherence, rhyme variety, grammar, originality, read_aloud clarity]} +adaptation: {works_best_with: [rap, jazz_rap, experimental], can_adapt_to: [electronic, rock, spoken_word], topic_handling: conceptual_and_concrete_layers, emotional_range: high} +metrics: {syllable_density: 0.96, rhyme_density: 0.95, internal_rhyme: 0.96, melodic_bias: 0.15, narrative_bias: 0.5, abstraction: 0.56, aggression: 0.45, repetition: 0.2, flow_variability: 0.66, punchline_bias: 0.62, imagery: 0.68, directness: 0.5, emotional_intensity: 0.58, space: 0.24, breath_demand: 0.92} diff --git a/lyric_styles/03_chilled_conversational.yaml b/lyric_styles/03_chilled_conversational.yaml new file mode 100644 index 0000000..51c7466 --- /dev/null +++ b/lyric_styles/03_chilled_conversational.yaml @@ -0,0 +1,13 @@ +style: {id: chilled_conversational, name: Chilled Conversational Flow, version: "1.0", category: voice_engine, description: Natural speech with understated rhyme and breathing room} +identity: {core_philosophy: Sound like a person thinking aloud with musical control, listener_impression: effortless and intimate, primary_strengths: [authenticity, smoothness, understatement], intentionally_avoids: [forced rhyme, grandstanding, filler]} +rhythm: {pace: relaxed, syllable_density: 0.42, average_syllables_per_bar: 9, line_length: irregular, rhythmic_subdivision: mostly_even, cadence_character: spoken_smooth, syncopation: 0.42, pause_usage: generous, enjambment: 0.62, flow_variation: 0.5, flow_switch_frequency: 0.18} +rhyme: {overall_density: 0.4, end_rhyme_frequency: 0.3, internal_rhyme_frequency: 0.35, multisyllabic_rhyme_level: 0.2, rhyme_chain_length: 1, slant_rhyme_usage: 0.65, consonance: 0.4, assonance: 0.48, rhyme_resolution: occasional, rhyme_predictability: 0.3} +language: {vocabulary_complexity: 0.4, sentence_complexity: 0.48, conversational_level: 0.9, metaphor_density: 0.3, wordplay_density: 0.2, imagery_density: 0.55, abstraction_level: 0.3, directness: 0.76, profanity_behavior: natural_context_only, filler_tolerance: 0.12} +delivery: {perceived_energy: 0.38, aggression: 0.12, smoothness: 0.82, emotional_intensity: 0.52, vocal_space: 0.72, breath_demand: 0.3, emphasis_behavior: subtle} +composition: {verse_behavior: conversational_observations, hook_behavior: simple_memorable_phrase, bridge_behavior: perspective_shift, opening_behavior: specific_detail, closing_behavior: understated_insight, repetition_level: 0.42, callback_usage: 0.5, progression_style: gradual} +storytelling: {narrative_priority: 0.58, perspective: first_or_second_person, scene_detail: 0.62, continuity: 0.7, character_usage: occasional, temporal_progression: natural, payoff_behavior: emotional_observation} +technical_rules: {hard_rules: ["Use natural sentences", "Leave audible breathing room", "Rhyme only when it sounds unforced"], preferred_rules: ["Use concrete small details", "Allow uneven line lengths", "Prefer slant rhyme"], optional_behaviors: ["Spoken aside", "One repeated anchor"]} +anti_patterns: {never_do: ["constant perfect rhyme", "generic wisdom", "fake casual filler"], avoid_overusing: ["you know", "late night imagery", "same sentence opener"], warning_signs: ["sounds written instead of spoken"]} +generation_guidance: {planning_method: list_real_observations_then_find_emotional_thread, writing_order: speech_draft_then_musical_edit, revision_method: remove_any_line_not_sounding_natural, quality_checks: [speakability, specificity, restraint, emotional honesty]} +adaptation: {works_best_with: [hip_hop, lo_fi, indie, pop], can_adapt_to: [rock, rnb], topic_handling: personal_observation, emotional_range: broad} +metrics: {syllable_density: 0.42, rhyme_density: 0.4, internal_rhyme: 0.35, melodic_bias: 0.45, narrative_bias: 0.58, abstraction: 0.3, aggression: 0.12, repetition: 0.42, flow_variability: 0.5, punchline_bias: 0.18, imagery: 0.55, directness: 0.76, emotional_intensity: 0.52, space: 0.72, breath_demand: 0.3} diff --git a/lyric_styles/04_punchline.yaml b/lyric_styles/04_punchline.yaml new file mode 100644 index 0000000..665dd55 --- /dev/null +++ b/lyric_styles/04_punchline.yaml @@ -0,0 +1,13 @@ +style: {id: punchline, name: Bar-Heavy Punchline Craft, version: "1.0", category: idea_engine, description: "Compact setups, misdirection and intelligent payoffs"} +identity: {core_philosophy: Each bar pair earns attention with a precise turn, listener_impression: quotable and sharp, primary_strengths: [wordplay, compression, payoff], intentionally_avoids: [corny_jokes, empty flexing, obvious setups]} +rhythm: {pace: medium, syllable_density: 0.68, average_syllables_per_bar: 12, line_length: compact, rhythmic_subdivision: varied, cadence_character: setup_then_snap, syncopation: 0.62, pause_usage: before_payoff, enjambment: 0.4, flow_variation: 0.48, flow_switch_frequency: 0.25} +rhyme: {overall_density: 0.65, end_rhyme_frequency: 0.58, internal_rhyme_frequency: 0.62, multisyllabic_rhyme_level: 0.55, rhyme_chain_length: 2, slant_rhyme_usage: 0.55, consonance: 0.62, assonance: 0.58, rhyme_resolution: payoff_aligned, rhyme_predictability: 0.28} +language: {vocabulary_complexity: 0.7, sentence_complexity: 0.62, conversational_level: 0.5, metaphor_density: 0.7, wordplay_density: 0.92, imagery_density: 0.58, abstraction_level: 0.42, directness: 0.62, profanity_behavior: purposeful, filler_tolerance: 0.03} +delivery: {perceived_energy: 0.76, aggression: 0.55, smoothness: 0.5, emotional_intensity: 0.42, vocal_space: 0.35, breath_demand: 0.62, emphasis_behavior: land_the_turn} +composition: {verse_behavior: setup_payoff_pairs, hook_behavior: quotable_refrain, bridge_behavior: change_angle, opening_behavior: establish_premise, closing_behavior: strongest_reframe, repetition_level: 0.28, callback_usage: 0.68, progression_style: escalating_stakes} +storytelling: {narrative_priority: 0.38, perspective: flexible, scene_detail: 0.4, continuity: 0.5, character_usage: optional, temporal_progression: flexible, payoff_behavior: misdirection_then_clarity} +technical_rules: {hard_rules: ["Every bar pair contains a meaningful turn", "Prefer implication over explanation", "Punchlines must serve the subject"], preferred_rules: ["Use double meaning with context", "Keep wording compact", "Vary payoff placement"], optional_behaviors: ["Callback punchline", "Delayed reveal"]} +anti_patterns: {never_do: ["dad jokes", "cliches", "forced double entendres"], avoid_overusing: ["same punchline shape", "bragging", "similes"], warning_signs: ["the line needs explanation to work"]} +generation_guidance: {planning_method: create_claim_obstacle_reversal_pairs, writing_order: idea_then_setup_then_sound_edit, revision_method: cut_explanation_after_payoff, quality_checks: [originality, clarity, relevance, quotability]} +adaptation: {works_best_with: [rap, grime, boom_bap], can_adapt_to: [pop, rock, electronic], topic_handling: premise_and_observation, emotional_range: medium} +metrics: {syllable_density: 0.68, rhyme_density: 0.65, internal_rhyme: 0.62, melodic_bias: 0.22, narrative_bias: 0.38, abstraction: 0.42, aggression: 0.55, repetition: 0.28, flow_variability: 0.48, punchline_bias: 0.92, imagery: 0.58, directness: 0.62, emotional_intensity: 0.42, space: 0.35, breath_demand: 0.62} diff --git a/lyric_styles/05_cinematic_story.yaml b/lyric_styles/05_cinematic_story.yaml new file mode 100644 index 0000000..444f482 --- /dev/null +++ b/lyric_styles/05_cinematic_story.yaml @@ -0,0 +1,13 @@ +style: {id: cinematic_story, name: Cinematic Storytelling, version: "1.0", category: narrative_engine, description: "Scene-led narrative with characters, consequence and callbacks"} +identity: {core_philosophy: Show a film through specific actions and sensory detail, listener_impression: immersive and consequential, primary_strengths: [scenes, continuity, payoff], intentionally_avoids: [generic narration, exposition dumps, disconnected images]} +rhythm: {pace: variable, syllable_density: 0.54, average_syllables_per_bar: 10, line_length: varied, rhythmic_subdivision: scene_dependent, cadence_character: visual_and_natural, syncopation: 0.44, pause_usage: dramatic, enjambment: 0.7, flow_variation: 0.55, flow_switch_frequency: 0.3} +rhyme: {overall_density: 0.48, end_rhyme_frequency: 0.38, internal_rhyme_frequency: 0.4, multisyllabic_rhyme_level: 0.3, rhyme_chain_length: 2, slant_rhyme_usage: 0.62, consonance: 0.45, assonance: 0.52, rhyme_resolution: scene_end, rhyme_predictability: 0.4} +language: {vocabulary_complexity: 0.62, sentence_complexity: 0.72, conversational_level: 0.52, metaphor_density: 0.42, wordplay_density: 0.22, imagery_density: 0.9, abstraction_level: 0.34, directness: 0.62, profanity_behavior: character_based, filler_tolerance: 0.04} +delivery: {perceived_energy: 0.62, aggression: 0.3, smoothness: 0.58, emotional_intensity: 0.76, vocal_space: 0.48, breath_demand: 0.45, emphasis_behavior: action_and_reveal} +composition: {verse_behavior: sequential_scenes, hook_behavior: thematic_refrain, bridge_behavior: time_or_perspective_shift, opening_behavior: in_media_res, closing_behavior: consequence_or_image, repetition_level: 0.38, callback_usage: 0.88, progression_style: rising_tension} +storytelling: {narrative_priority: 0.96, perspective: chosen_and_consistent, scene_detail: 0.92, continuity: 0.94, character_usage: central, temporal_progression: clear, payoff_behavior: earned_consequence} +technical_rules: {hard_rules: ["Use locations, actions and sensory details", "Maintain continuity of people and objects", "Show events rather than summarize them", "End with consequence or changed understanding"], preferred_rules: ["Seed a detail that returns later", "Use dialogue sparingly", "Let imagery carry emotion"], optional_behaviors: ["Unreliable perspective", "Nonlinear reveal"]} +anti_patterns: {never_do: ["generic life-story summary", "unearned twist", "nameless characters doing vague things"], avoid_overusing: ["weather metaphors", "explaining emotion", "random flashbacks"], warning_signs: ["removing the rhyme leaves no scene"]} +generation_guidance: {planning_method: define protagonist_want_obstacle_change_and_three_scenes, writing_order: beat_sheet_then_scene_draft_then_sound_edit, revision_method: replace abstractions_with_observable_actions, quality_checks: [continuity, sensory specificity, stakes, ending]} +adaptation: {works_best_with: [soundtrack, rap, folk, rock], can_adapt_to: [pop, electronic], topic_handling: character_and_event_based, emotional_range: very_high} +metrics: {syllable_density: 0.54, rhyme_density: 0.48, internal_rhyme: 0.4, melodic_bias: 0.3, narrative_bias: 0.96, abstraction: 0.34, aggression: 0.3, repetition: 0.38, flow_variability: 0.55, punchline_bias: 0.2, imagery: 0.9, directness: 0.62, emotional_intensity: 0.76, space: 0.48, breath_demand: 0.45} diff --git a/lyric_styles/06_melodic_emotional.yaml b/lyric_styles/06_melodic_emotional.yaml new file mode 100644 index 0000000..a062864 --- /dev/null +++ b/lyric_styles/06_melodic_emotional.yaml @@ -0,0 +1,13 @@ +style: {id: melodic_emotional, name: Melodic Emotional Anchors, version: "1.0", category: melodic_engine, description: Singable emotional phrases with meaningful detail} +identity: {core_philosophy: Make feeling memorable through sound and specific truth, listener_impression: vulnerable and hookable, primary_strengths: [emotion, vowels, anchors], intentionally_avoids: [generic pop cliches, empty repetition, melodrama]} +rhythm: {pace: medium, syllable_density: 0.48, average_syllables_per_bar: 9, line_length: clean_phrase_shapes, rhythmic_subdivision: mostly_even, cadence_character: singable, syncopation: 0.3, pause_usage: phrase_breaths, enjambment: 0.38, flow_variation: 0.32, flow_switch_frequency: 0.18} +rhyme: {overall_density: 0.5, end_rhyme_frequency: 0.48, internal_rhyme_frequency: 0.3, multisyllabic_rhyme_level: 0.24, rhyme_chain_length: 2, slant_rhyme_usage: 0.58, consonance: 0.28, assonance: 0.72, rhyme_resolution: hook_aligned, rhyme_predictability: 0.45} +language: {vocabulary_complexity: 0.46, sentence_complexity: 0.42, conversational_level: 0.6, metaphor_density: 0.5, wordplay_density: 0.18, imagery_density: 0.62, abstraction_level: 0.38, directness: 0.58, profanity_behavior: contextual, filler_tolerance: 0.05} +delivery: {perceived_energy: 0.58, aggression: 0.12, smoothness: 0.84, emotional_intensity: 0.92, vocal_space: 0.5, breath_demand: 0.38, emphasis_behavior: vowel_and_anchor_emphasis} +composition: {verse_behavior: detail_to_feeling, hook_behavior: repeated_emotional_anchor, bridge_behavior: emotional_reframe, opening_behavior: intimate_image, closing_behavior: unresolved_or_resolved_echo, repetition_level: 0.7, callback_usage: 0.62, progression_style: emotional_rise} +storytelling: {narrative_priority: 0.54, perspective: first_person_preferred, scene_detail: 0.62, continuity: 0.6, character_usage: optional, temporal_progression: emotional, payoff_behavior: emotional_truth} +technical_rules: {hard_rules: ["Build one memorable anchor phrase", "Use vowel-friendly words in hooks", "Repeat with purposeful variation"], preferred_rules: ["Use concrete detail before abstraction", "Keep melodic phrases concise", "Let verses deepen the hook"], optional_behaviors: ["Melodic rap pre-hook", "Wordless space between phrases"]} +anti_patterns: {never_do: ["generic heartbreak slogans", "repetition without changed meaning", "overstuffed hooks"], avoid_overusing: ["love, pain, night", "perfect rhymes"], warning_signs: ["emotion is announced rather than felt"]} +generation_guidance: {planning_method: name_emotion_image_and_anchor, writing_order: hook_core_then_verses_then_bridge, revision_method: sing_aloud_and_replace_awkward_consonants, quality_checks: [hook_memory, emotional_specificity, vowel_flow, progression]} +adaptation: {works_best_with: [pop, rnb, melodic_rap], can_adapt_to: [rock, electronic, folk], topic_handling: emotional_anchor_and_detail, emotional_range: very_high} +metrics: {syllable_density: 0.48, rhyme_density: 0.5, internal_rhyme: 0.3, melodic_bias: 0.9, narrative_bias: 0.54, abstraction: 0.38, aggression: 0.12, repetition: 0.7, flow_variability: 0.32, punchline_bias: 0.15, imagery: 0.62, directness: 0.58, emotional_intensity: 0.92, space: 0.5, breath_demand: 0.38} diff --git a/lyric_styles/07_raw_direct.yaml b/lyric_styles/07_raw_direct.yaml new file mode 100644 index 0000000..7434468 --- /dev/null +++ b/lyric_styles/07_raw_direct.yaml @@ -0,0 +1,13 @@ +style: {id: raw_direct, name: Raw Direct Precision, version: "1.0", category: impact_engine, description: Concrete forceful language without ornament} +identity: {core_philosophy: Say the hard thing plainly and make details carry weight, listener_impression: believable and immediate, primary_strengths: [impact, honesty, concrete imagery], intentionally_avoids: [intellectual decoration, vague metaphor, fake bravado]} +rhythm: {pace: medium, syllable_density: 0.46, average_syllables_per_bar: 8, line_length: short, rhythmic_subdivision: blunt, cadence_character: forceful, syncopation: 0.35, pause_usage: emphatic, enjambment: 0.3, flow_variation: 0.28, flow_switch_frequency: 0.12} +rhyme: {overall_density: 0.35, end_rhyme_frequency: 0.32, internal_rhyme_frequency: 0.24, multisyllabic_rhyme_level: 0.12, rhyme_chain_length: 1, slant_rhyme_usage: 0.48, consonance: 0.56, assonance: 0.35, rhyme_resolution: occasional, rhyme_predictability: 0.5} +language: {vocabulary_complexity: 0.3, sentence_complexity: 0.3, conversational_level: 0.72, metaphor_density: 0.18, wordplay_density: 0.12, imagery_density: 0.68, abstraction_level: 0.16, directness: 0.96, profanity_behavior: only_if_authentic, filler_tolerance: 0.02} +delivery: {perceived_energy: 0.82, aggression: 0.76, smoothness: 0.38, emotional_intensity: 0.72, vocal_space: 0.34, breath_demand: 0.45, emphasis_behavior: strong_verbs_and_nouns} +composition: {verse_behavior: accumulating_facts, hook_behavior: blunt_statement, bridge_behavior: confrontation_or_release, opening_behavior: immediate_fact, closing_behavior: final_plain_truth, repetition_level: 0.4, callback_usage: 0.5, progression_style: pressure} +storytelling: {narrative_priority: 0.62, perspective: first_person_or_witness, scene_detail: 0.74, continuity: 0.7, character_usage: grounded, temporal_progression: linear, payoff_behavior: consequence} +technical_rules: {hard_rules: ["Prefer strong verbs", "Use concrete nouns and observable details", "Make simple language precise"], preferred_rules: ["Use dialogue fragments", "Keep lines forceful", "Let silence create threat or weight"], optional_behaviors: ["One plain refrain", "Documentary detail"]} +anti_patterns: {never_do: ["generic gangster cliches", "luxury flexing without story", "excessive metaphor"], avoid_overusing: ["blood, streets, demons", "short lines with no information"], warning_signs: ["simple words but no concrete event"]} +generation_guidance: {planning_method: collect_five_specific_facts_and_one_stakes_statement, writing_order: facts_then_pressure_then_refrain, revision_method: replace_abstract_nouns_with_actions, quality_checks: [believability, specificity, force, restraint]} +adaptation: {works_best_with: [rap, punk, rock], can_adapt_to: [electronic, folk], topic_handling: direct_observation, emotional_range: high} +metrics: {syllable_density: 0.46, rhyme_density: 0.35, internal_rhyme: 0.24, melodic_bias: 0.18, narrative_bias: 0.62, abstraction: 0.16, aggression: 0.76, repetition: 0.4, flow_variability: 0.28, punchline_bias: 0.3, imagery: 0.68, directness: 0.96, emotional_intensity: 0.72, space: 0.34, breath_demand: 0.45} diff --git a/lyric_styles/08_abstract_psychedelic.yaml b/lyric_styles/08_abstract_psychedelic.yaml new file mode 100644 index 0000000..95c6211 --- /dev/null +++ b/lyric_styles/08_abstract_psychedelic.yaml @@ -0,0 +1,13 @@ +style: {id: abstract_psychedelic, name: Abstract Dream Logic, version: "1.0", category: imagery_engine, description: Surreal connected imagery with emotional or conceptual logic} +identity: {core_philosophy: Make unexpected images answer the same hidden question, listener_impression: strange but meaningful, primary_strengths: [originality, symbolism, sensory crossover], intentionally_avoids: [random nonsense, decorative weirdness, empty obscurity]} +rhythm: {pace: variable, syllable_density: 0.58, average_syllables_per_bar: 11, line_length: irregular, rhythmic_subdivision: exploratory, cadence_character: drifting_then_locked, syncopation: 0.7, pause_usage: dramatic, enjambment: 0.78, flow_variation: 0.72, flow_switch_frequency: 0.45} +rhyme: {overall_density: 0.52, end_rhyme_frequency: 0.3, internal_rhyme_frequency: 0.48, multisyllabic_rhyme_level: 0.42, rhyme_chain_length: 2, slant_rhyme_usage: 0.8, consonance: 0.62, assonance: 0.72, rhyme_resolution: associative, rhyme_predictability: 0.12} +language: {vocabulary_complexity: 0.72, sentence_complexity: 0.76, conversational_level: 0.28, metaphor_density: 0.9, wordplay_density: 0.55, imagery_density: 0.96, abstraction_level: 0.9, directness: 0.28, profanity_behavior: contextual, filler_tolerance: 0.02} +delivery: {perceived_energy: 0.64, aggression: 0.2, smoothness: 0.45, emotional_intensity: 0.78, vocal_space: 0.5, breath_demand: 0.42, emphasis_behavior: image_and_texture} +composition: {verse_behavior: linked_fragments, hook_behavior: symbolic_anchor, bridge_behavior: reality_shift, opening_behavior: arresting_image, closing_behavior: image_recontextualization, repetition_level: 0.46, callback_usage: 0.82, progression_style: dream_logic_with_emotional_direction} +storytelling: {narrative_priority: 0.34, perspective: shifting_but_intentional, scene_detail: 0.74, continuity: 0.55, character_usage: symbolic, temporal_progression: nonlinear, payoff_behavior: thematic_recognition} +technical_rules: {hard_rules: ["Every strange image must connect to a subject emotion or theme", "Repeat symbols with changed meaning", "Preserve an emotional through-line"], preferred_rules: ["Use synesthesia", "Mix concrete sensory objects with abstraction", "Let grammar bend only for effect"], optional_behaviors: ["Fragmented perspective", "Invented compound image"]} +anti_patterns: {never_do: ["random noun lists", "unexplained surrealism", "cliche dream imagery"], avoid_overusing: ["mirrors, galaxies, oceans, neon", "every line as a metaphor"], warning_signs: ["cannot state what the song feels about"]} +generation_guidance: {planning_method: choose_theme_then_symbol_set_then_association_map, writing_order: sensory_images_then_connections_then_refrain, revision_method: remove_any_image_without_emotional_job, quality_checks: [coherence, originality, symbol return, emotional legibility]} +adaptation: {works_best_with: [experimental, electronic, art_pop], can_adapt_to: [rap, rock, ambient], topic_handling: symbolic_translation, emotional_range: high} +metrics: {syllable_density: 0.58, rhyme_density: 0.52, internal_rhyme: 0.48, melodic_bias: 0.38, narrative_bias: 0.34, abstraction: 0.9, aggression: 0.2, repetition: 0.46, flow_variability: 0.72, punchline_bias: 0.18, imagery: 0.96, directness: 0.28, emotional_intensity: 0.78, space: 0.5, breath_demand: 0.42} diff --git a/lyric_styles/09_minimalist_space.yaml b/lyric_styles/09_minimalist_space.yaml new file mode 100644 index 0000000..36d39be --- /dev/null +++ b/lyric_styles/09_minimalist_space.yaml @@ -0,0 +1,13 @@ +style: {id: minimalist_space, name: Minimal Space-Driven Writing, version: "1.0", category: economy_engine, description: Few high-value words with intentional silence} +identity: {core_philosophy: Every word must earn its sonic and emotional place, listener_impression: stark and memorable, primary_strengths: [economy, anchors, space], intentionally_avoids: [filler, explanation, over-writing]} +rhythm: {pace: slow_to_medium, syllable_density: 0.22, average_syllables_per_bar: 4, line_length: very_short, rhythmic_subdivision: sparse, cadence_character: spacious, syncopation: 0.52, pause_usage: structural, enjambment: 0.2, flow_variation: 0.35, flow_switch_frequency: 0.12} +rhyme: {overall_density: 0.28, end_rhyme_frequency: 0.25, internal_rhyme_frequency: 0.18, multisyllabic_rhyme_level: 0.08, rhyme_chain_length: 1, slant_rhyme_usage: 0.52, consonance: 0.32, assonance: 0.48, rhyme_resolution: occasional, rhyme_predictability: 0.42} +language: {vocabulary_complexity: 0.36, sentence_complexity: 0.2, conversational_level: 0.52, metaphor_density: 0.5, wordplay_density: 0.08, imagery_density: 0.62, abstraction_level: 0.42, directness: 0.7, profanity_behavior: rare, filler_tolerance: 0.0} +delivery: {perceived_energy: 0.34, aggression: 0.1, smoothness: 0.72, emotional_intensity: 0.68, vocal_space: 0.96, breath_demand: 0.12, emphasis_behavior: isolated_words} +composition: {verse_behavior: image_fragments, hook_behavior: mantra_anchor, bridge_behavior: silence_or_single_new_image, opening_behavior: one_precise_image, closing_behavior: leave_resonance, repetition_level: 0.78, callback_usage: 0.72, progression_style: accumulation_by_repetition} +storytelling: {narrative_priority: 0.3, perspective: flexible, scene_detail: 0.55, continuity: 0.5, character_usage: optional, temporal_progression: implied, payoff_behavior: listener_inference} +technical_rules: {hard_rules: ["Remove any unnecessary word", "Use silence as a compositional unit", "Repeat only phrases that gain meaning"], preferred_rules: ["Use strong nouns", "Leave lines unfinished when intentional", "Make the hook instantly memorable"], optional_behaviors: ["One-word response", "Long instrumental gap"]} +anti_patterns: {never_do: ["generic filler", "explaining the image", "padding short lines"], avoid_overusing: ["baby, fire, night", "three-line fragments everywhere"], warning_signs: ["low word count but low information"]} +generation_guidance: {planning_method: choose_three_images_and_one_anchor, writing_order: anchor_then_supporting_fragments_then_silence, revision_method: cut_thirty_percent_without_losing meaning, quality_checks: [value_per_word, memory, space, sonic_shape]} +adaptation: {works_best_with: [ambient, trap, indie], can_adapt_to: [pop, electronic, spoken_word], topic_handling: emblematic_images, emotional_range: high} +metrics: {syllable_density: 0.22, rhyme_density: 0.28, internal_rhyme: 0.18, melodic_bias: 0.62, narrative_bias: 0.3, abstraction: 0.42, aggression: 0.1, repetition: 0.78, flow_variability: 0.35, punchline_bias: 0.12, imagery: 0.62, directness: 0.7, emotional_intensity: 0.68, space: 0.96, breath_demand: 0.12} diff --git a/lyric_styles/10_progressive_switching.yaml b/lyric_styles/10_progressive_switching.yaml new file mode 100644 index 0000000..f5a1c19 --- /dev/null +++ b/lyric_styles/10_progressive_switching.yaml @@ -0,0 +1,13 @@ +style: {id: progressive_switching, name: Progressive Flow Switching, version: "1.0", category: evolution_engine, description: "Purposeful changes in cadence, density and perspective"} +identity: {core_philosophy: Let form evolve because the subject evolves, listener_impression: dynamic and intentional, primary_strengths: [contrast, progression, controlled surprise], intentionally_avoids: [random switches, complexity for display, sectionless chaos]} +rhythm: {pace: changing, syllable_density: 0.76, average_syllables_per_bar: 13, line_length: changing, rhythmic_subdivision: staged, cadence_character: evolving, syncopation: 0.78, pause_usage: resets, enjambment: 0.7, flow_variation: 0.94, flow_switch_frequency: 0.82} +rhyme: {overall_density: 0.7, end_rhyme_frequency: 0.48, internal_rhyme_frequency: 0.72, multisyllabic_rhyme_level: 0.68, rhyme_chain_length: 3, slant_rhyme_usage: 0.68, consonance: 0.72, assonance: 0.7, rhyme_resolution: section_dependent, rhyme_predictability: 0.18} +language: {vocabulary_complexity: 0.72, sentence_complexity: 0.74, conversational_level: 0.4, metaphor_density: 0.58, wordplay_density: 0.58, imagery_density: 0.62, abstraction_level: 0.52, directness: 0.5, profanity_behavior: contextual, filler_tolerance: 0.03} +delivery: {perceived_energy: 0.78, aggression: 0.5, smoothness: 0.46, emotional_intensity: 0.72, vocal_space: 0.32, breath_demand: 0.78, emphasis_behavior: transition_markers} +composition: {verse_behavior: sections_with_distinct_rules, hook_behavior: stabilizing_return, bridge_behavior: major_reset, opening_behavior: establish_baseline_then_change, closing_behavior: synthesize_modes, repetition_level: 0.32, callback_usage: 0.7, progression_style: escalation_and_reframe} +storytelling: {narrative_priority: 0.62, perspective: shifts_with_purpose, scene_detail: 0.58, continuity: 0.72, character_usage: optional, temporal_progression: progressive, payoff_behavior: form_and_meaning_converge} +technical_rules: {hard_rules: ["Every switch must mark a change in meaning, stakes or perspective", "Signal transitions through sound or image", "Return or resolve the opening idea"], preferred_rules: ["Contrast dense and sparse sections", "Change rhyme architecture at a section boundary", "Use a rhythmic reset before the final section"], optional_behaviors: ["Perspective switch", "Sentence-length inversion"]} +anti_patterns: {never_do: ["random cadence changes", "switches with no purpose", "constant maximal density"], avoid_overusing: ["same switch location", "technical jargon", "false complexity"], warning_signs: ["sections could be reordered with no effect"]} +generation_guidance: {planning_method: map_emotional_or_narrative_arc_to_three_formal_modes, writing_order: section_plan_then_distinct_drafts_then_transition_edit, revision_method: justify_each_switch_in_plain_language, quality_checks: [purpose, contrast, continuity, final synthesis]} +adaptation: {works_best_with: [progressive_rap, fusion, electronic], can_adapt_to: [rock, pop, jazz], topic_handling: evolving_argument_or_story, emotional_range: very_high} +metrics: {syllable_density: 0.76, rhyme_density: 0.7, internal_rhyme: 0.72, melodic_bias: 0.3, narrative_bias: 0.62, abstraction: 0.52, aggression: 0.5, repetition: 0.32, flow_variability: 0.94, punchline_bias: 0.42, imagery: 0.62, directness: 0.5, emotional_intensity: 0.72, space: 0.32, breath_demand: 0.78} diff --git a/lyric_styles/hiphop_30/01_fast_punchy.md b/lyric_styles/hiphop_30/01_fast_punchy.md new file mode 100644 index 0000000..3603fd5 --- /dev/null +++ b/lyric_styles/hiphop_30/01_fast_punchy.md @@ -0,0 +1,73 @@ +# Fast Punchy + +## Purpose +Create rapid, hard-hitting rap verses built from compact bars, immediate impact, and frequent memorable punchlines. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Very high +- **Delivery Speed:** Fast / double-time capable +- **Target Syllables:** 8–13 syllables per bar, with occasional shorter impact bars +- **Rhyme Density:** High +- **Internal Rhyme Density:** Medium-high +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** At least 1 strong punchline or payoff every 2 bars +- **Wordplay Level:** High +- **Metaphor Density:** Medium-high +- **Vocabulary:** Direct, vivid, compact +- **Storytelling Level:** Low-medium +- **Aggression:** High +- **Emotional Intensity:** Medium-high +- **Repetition:** Low outside hooks +- **Flow Variation:** Frequent micro-switches without losing momentum +- **Preferred Rhyme Schemes:** AA/BB, AAAA bursts, internal chains +- **Bar Structure:** Short clauses, hard stops, minimal setup time +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Open with impact within the first 2 bars. +- Keep most bars compact enough for fast delivery. +- Use strong stressed rhyme words at line endings. +- Include internal rhymes in at least half the bars. +- Deliver a payoff, flip, boast, image, or punchline at least every 2 bars. +- Use verbs and concrete nouns more than vague adjectives. +- Keep transitions fast; avoid long narrative detours. + +## Avoid +Long explanations, filler bars, soft openings, overly complex sentence structures that slow delivery + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does the verse feel fast even when read silently? +- [ ] Are at least 50% of bars carrying internal rhyme or rhythmic echo? +- [ ] Is there a memorable impact line at least every 2 bars? +- [ ] Could any bar be shortened without losing meaning? If yes, tighten it. +- [ ] Are filler connectors removed? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/02_syllable_dense.md b/lyric_styles/hiphop_30/02_syllable_dense.md new file mode 100644 index 0000000..7a30b17 --- /dev/null +++ b/lyric_styles/hiphop_30/02_syllable_dense.md @@ -0,0 +1,72 @@ +# Syllable Dense + +## Purpose +Maximize technical density while keeping the verse understandable and performable. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Medium-fast to fast +- **Target Syllables:** 12–18 syllables per bar +- **Rhyme Density:** Very high +- **Internal Rhyme Density:** Very high +- **Multisyllabic Rhyme Level:** Very high +- **Punchline Frequency:** 1 payoff every 3–4 bars +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Advanced but natural +- **Storytelling Level:** Medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low +- **Flow Variation:** Dense but controlled pockets +- **Preferred Rhyme Schemes:** Multisyllabic chains, nested internal schemes, extended rhyme families +- **Bar Structure:** Layered clauses with consistent rhythm +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Use multisyllabic rhyme families across groups of 2–4 bars. +- Place at least two rhyme events in most bars. +- Maintain semantic coherence despite density. +- Prefer natural phrases over forced rhyme words. +- Vary rhyme placement between internal, medial, and end rhyme. +- Keep a discernible central idea in each 4-bar block. + +## Avoid +Word salad, forced rhymes, unnatural grammar, technicality without meaning + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Do most bars contain two or more rhyme events? +- [ ] Are rhyme chains sustained beyond a single couplet? +- [ ] Does every dense phrase still make sense? +- [ ] Would a skilled rapper be able to perform the wording naturally? +- [ ] Remove any line that exists only to satisfy a rhyme. + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/03_machine_gun_flow.md b/lyric_styles/hiphop_30/03_machine_gun_flow.md new file mode 100644 index 0000000..1778615 --- /dev/null +++ b/lyric_styles/hiphop_30/03_machine_gun_flow.md @@ -0,0 +1,70 @@ +# Machine Gun Flow + +## Purpose +Create relentless rapid-fire delivery using short rhythmic syllable clusters and tightly repeated cadence patterns. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Extreme +- **Delivery Speed:** Very fast +- **Target Syllables:** 10–16 syllables per bar in compact clusters +- **Rhyme Density:** High +- **Internal Rhyme Density:** Very high +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** Medium +- **Wordplay Level:** Medium-high +- **Metaphor Density:** Medium +- **Vocabulary:** Compact and percussive +- **Storytelling Level:** Low-medium +- **Aggression:** High +- **Emotional Intensity:** High +- **Repetition:** Medium rhythmic repetition +- **Flow Variation:** Rapid repeating pockets with controlled resets +- **Preferred Rhyme Schemes:** Internal triplets, repeated consonant patterns, chained rhymes +- **Bar Structure:** Short bursts separated by tiny pauses +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Favor short words and consonant-heavy phrasing. +- Build bars from 2–4 rapid rhythmic clusters. +- Use repeated cadence patterns for 2–4 bars before switching. +- Insert occasional shorter reset bars for breath and contrast. +- Keep rhyme hits close together. + +## Avoid +Long vowels, slow phrases, long setup bars, excessive punctuation + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does the verse support fast articulation? +- [ ] Are there clear recurring rhythmic pockets? +- [ ] Are long, sluggish phrases minimized? +- [ ] Does the flow reset before becoming monotonous? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/04_battle_rap.md b/lyric_styles/hiphop_30/04_battle_rap.md new file mode 100644 index 0000000..703ec4c --- /dev/null +++ b/lyric_styles/hiphop_30/04_battle_rap.md @@ -0,0 +1,70 @@ +# Battle Rap + +## Purpose +Create competitive rap built around setups, flips, layered punchlines, and rhetorical dominance. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 9–15 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** At least 1 major punch every 2 bars +- **Wordplay Level:** Very high +- **Metaphor Density:** Very high +- **Vocabulary:** Sharp, specific, witty +- **Storytelling Level:** Low +- **Aggression:** Very high +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Varied to support setups and payoffs +- **Preferred Rhyme Schemes:** Couplets, extended schemes, setup/payoff pairs +- **Bar Structure:** Setup → tension → flip/punch +- **Hook Compatibility:** Low-medium + +## Mandatory Writing Rules +- Build clear setup/payoff relationships. +- Use double meanings, reversals, comparisons, or angle-based attacks. +- Make punchlines understandable on first listen but deeper on replay. +- Avoid generic insult filler. +- Use callbacks when possible. + +## Avoid +Generic threats, empty insults, random violence, weak comparisons, predictable punchlines + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does every 2-bar unit contain tension or payoff? +- [ ] Are punches specific rather than generic? +- [ ] Is the wordplay understandable? +- [ ] Are there at least two layered lines per 8 bars? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/05_street_grit.md b/lyric_styles/hiphop_30/05_street_grit.md new file mode 100644 index 0000000..7cee711 --- /dev/null +++ b/lyric_styles/hiphop_30/05_street_grit.md @@ -0,0 +1,70 @@ +# Street Grit + +## Purpose +Create grounded, serious street-centered rap with believable details, restraint, and lived-in atmosphere. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium +- **Target Syllables:** 8–14 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Low-medium +- **Wordplay Level:** Medium +- **Metaphor Density:** Medium +- **Vocabulary:** Direct, concrete, realistic +- **Storytelling Level:** High +- **Aggression:** Medium-high +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Steady and grounded +- **Preferred Rhyme Schemes:** ABAB, AABB, loose narrative rhyme +- **Bar Structure:** Scene/detail/consequence +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Use concrete environments, objects, sounds, and consequences. +- Prioritize believable details over exaggerated claims. +- Maintain a serious grounded voice. +- Include tension between ambition, pressure, loyalty, or consequence. +- Keep metaphors secondary to realism. + +## Avoid +Cartoonish criminal clichés, excessive glamorization, vague tough talk, melodrama + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Could the scene be visualized? +- [ ] Do details feel specific rather than generic? +- [ ] Is the tone serious and restrained? +- [ ] Does each section communicate consequence or pressure? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/06_boom_bap_classic.md b/lyric_styles/hiphop_30/06_boom_bap_classic.md new file mode 100644 index 0000000..7523d98 --- /dev/null +++ b/lyric_styles/hiphop_30/06_boom_bap_classic.md @@ -0,0 +1,70 @@ +# Boom Bap Classic + +## Purpose +Create classic head-nod rap with balanced bars, clear rhyme endings, strong cadence, and traditional verse craft. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium +- **Target Syllables:** 9–14 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium-high +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** Medium-high +- **Vocabulary:** Classic lyrical, concrete +- **Storytelling Level:** Medium +- **Aggression:** Medium +- **Emotional Intensity:** Medium +- **Repetition:** Low-medium +- **Flow Variation:** Steady 4/4 pocket +- **Preferred Rhyme Schemes:** AABB, ABAB, AAAA sections +- **Bar Structure:** Balanced 4-bar phrases +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Use strong end-rhyme anchors. +- Structure ideas in 4-bar blocks. +- Include internal rhymes without overcrowding. +- Keep cadence suitable for a head-nod beat. +- Prioritize quotable bars and rhythmic clarity. + +## Avoid +Trap-style repetitive filler, overlong run-ons, excessive melodic phrasing + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does each 4-bar block feel complete? +- [ ] Are end rhymes clearly audible? +- [ ] Would the bars sit naturally over a classic drum break? +- [ ] Is technicality balanced with clarity? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/07_underground_abstract.md b/lyric_styles/hiphop_30/07_underground_abstract.md new file mode 100644 index 0000000..fc2d11f --- /dev/null +++ b/lyric_styles/hiphop_30/07_underground_abstract.md @@ -0,0 +1,70 @@ +# Underground Abstract + +## Purpose +Create unconventional, cerebral rap using surreal imagery, layered symbolism, and unpredictable associative writing. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Variable +- **Target Syllables:** 8–16 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** Low-medium +- **Wordplay Level:** Very high +- **Metaphor Density:** Very high +- **Vocabulary:** Unusual, vivid, intelligent +- **Storytelling Level:** Low-medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium-high +- **Repetition:** Very low +- **Flow Variation:** Unpredictable but deliberate +- **Preferred Rhyme Schemes:** Slant rhyme, internal webs, non-obvious extended schemes +- **Bar Structure:** Associative images linked by theme +- **Hook Compatibility:** Low-medium + +## Mandatory Writing Rules +- Use unusual but interpretable imagery. +- Link abstract lines through a shared emotional or conceptual thread. +- Favor slant rhyme and internal rhyme over obvious couplets. +- Allow ambiguity without losing coherence. +- Use surprising nouns, verbs, and image combinations. + +## Avoid +Random nonsense, fake profundity, thesaurus dumping, incoherent symbolism + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Is there a hidden thematic thread? +- [ ] Are images surprising but meaningful? +- [ ] Does abstraction feel intentional rather than random? +- [ ] Are obvious clichés minimized? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/08_chilled_flow.md b/lyric_styles/hiphop_30/08_chilled_flow.md new file mode 100644 index 0000000..3a03255 --- /dev/null +++ b/lyric_styles/hiphop_30/08_chilled_flow.md @@ -0,0 +1,70 @@ +# Chilled Flow + +## Purpose +Create relaxed, effortless rap with conversational phrasing, space, and smooth rhythmic movement. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Low-medium +- **Delivery Speed:** Slow-medium +- **Target Syllables:** 7–12 syllables per bar +- **Rhyme Density:** Medium +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Low-medium +- **Punchline Frequency:** Low +- **Wordplay Level:** Medium +- **Metaphor Density:** Medium +- **Vocabulary:** Natural, conversational +- **Storytelling Level:** Medium +- **Aggression:** Low +- **Emotional Intensity:** Medium-high +- **Repetition:** Medium +- **Flow Variation:** Laid-back with delayed entrances and space +- **Preferred Rhyme Schemes:** Loose AABB/ABAB, slant rhyme +- **Bar Structure:** Longer phrasing with breathing room +- **Hook Compatibility:** Very high + +## Mandatory Writing Rules +- Leave rhythmic space between ideas. +- Use conversational syntax. +- Keep rhyme placement smooth rather than obvious. +- Favor atmosphere and feeling over density. +- Allow a few simple repeated phrases. + +## Avoid +Overstuffed bars, constant punchlines, hyperactive rhyme chains, aggressive delivery + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does the verse feel effortless rather than technically crowded? +- [ ] Are there enough pauses and open spaces? +- [ ] Does the language sound natural when spoken? +- [ ] Is the mood consistent? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/09_smooth_storyteller.md b/lyric_styles/hiphop_30/09_smooth_storyteller.md new file mode 100644 index 0000000..c12ec76 --- /dev/null +++ b/lyric_styles/hiphop_30/09_smooth_storyteller.md @@ -0,0 +1,70 @@ +# Smooth Storyteller + +## Purpose +Tell a vivid narrative with clear characters, settings, progression, and an emotionally satisfying arc. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Medium +- **Target Syllables:** 9–15 syllables per bar +- **Rhyme Density:** Medium +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Low +- **Wordplay Level:** Medium +- **Metaphor Density:** Medium +- **Vocabulary:** Visual and natural +- **Storytelling Level:** Very high +- **Aggression:** Variable +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Smooth and consistent +- **Preferred Rhyme Schemes:** Loose narrative rhyme, ABAB, slant rhyme +- **Bar Structure:** Scene → action → consequence → reflection +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Establish who, where, and what early. +- Advance the narrative every 2–4 bars. +- Use sensory details. +- Maintain point of view. +- End sections with consequences, realizations, or turning points. + +## Avoid +Plot jumps, unexplained characters, excessive technical rhyming, unrelated flex bars + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can the listener follow the story without explanation? +- [ ] Does every 4-bar section move the plot forward? +- [ ] Are characters and locations clear? +- [ ] Does the ending connect to the opening? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/10_punchline_heavy.md b/lyric_styles/hiphop_30/10_punchline_heavy.md new file mode 100644 index 0000000..ff231de --- /dev/null +++ b/lyric_styles/hiphop_30/10_punchline_heavy.md @@ -0,0 +1,70 @@ +# Punchline Heavy + +## Purpose +Produce a high concentration of quotable lines, flips, comparisons, jokes, and clever payoffs. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 8–14 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** At least 1 notable punch every 1–2 bars +- **Wordplay Level:** Very high +- **Metaphor Density:** Very high +- **Vocabulary:** Compact and precise +- **Storytelling Level:** Low +- **Aggression:** Medium-high +- **Emotional Intensity:** Medium +- **Repetition:** Very low +- **Flow Variation:** Built to emphasize payoffs +- **Preferred Rhyme Schemes:** Couplets and setup/payoff chains +- **Bar Structure:** Setup → punch, or standalone quotable bar +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Deliver frequent standalone quotables. +- Use comparisons, reversals, double meanings, or unexpected endings. +- Keep setups short. +- Make payoffs land on strong rhythmic positions. +- Avoid repeating the same wordplay mechanism too often. + +## Avoid +Long narratives, filler setup, predictable similes, recycled clichés + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Is there a quotable line at least every 2 bars? +- [ ] Are punches varied in mechanism? +- [ ] Can weak setup bars be shortened? +- [ ] Do punchlines land clearly? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/11_wordplay_technician.md b/lyric_styles/hiphop_30/11_wordplay_technician.md new file mode 100644 index 0000000..a8bc163 --- /dev/null +++ b/lyric_styles/hiphop_30/11_wordplay_technician.md @@ -0,0 +1,70 @@ +# Wordplay Technician + +## Purpose +Center the verse on linguistic manipulation: homophones, doubles, semantic flips, compound meanings, and layered phrasing. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 9–15 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** High +- **Wordplay Level:** Extreme +- **Metaphor Density:** High +- **Vocabulary:** Precise and flexible +- **Storytelling Level:** Low-medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low +- **Flow Variation:** Clear enough to preserve entendres +- **Preferred Rhyme Schemes:** Extended rhyme families, homophone chains +- **Bar Structure:** Setup → linguistic pivot → payoff +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Use at least one meaningful wordplay device every 2 bars. +- Prefer double meanings that work grammatically in both interpretations. +- Combine rhyme and semantic play where possible. +- Use callbacks to earlier word choices. +- Keep the surface meaning coherent. + +## Avoid +Unclear puns, forced homophones, random dictionary words, wordplay that breaks syntax + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does each key wordplay line have a clear surface meaning? +- [ ] Is the second meaning discoverable? +- [ ] Are homophones natural? +- [ ] Are devices varied rather than repeated mechanically? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/12_internal_rhyme_heavy.md b/lyric_styles/hiphop_30/12_internal_rhyme_heavy.md new file mode 100644 index 0000000..83286f8 --- /dev/null +++ b/lyric_styles/hiphop_30/12_internal_rhyme_heavy.md @@ -0,0 +1,70 @@ +# Internal Rhyme Heavy + +## Purpose +Create verses where rhyme movement happens continuously inside the bar, not only at the line endings. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 11–17 syllables per bar +- **Rhyme Density:** Very high +- **Internal Rhyme Density:** Extreme +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** Medium-high +- **Vocabulary:** Flexible +- **Storytelling Level:** Medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low +- **Flow Variation:** Rolling and continuous +- **Preferred Rhyme Schemes:** Internal chains, mirrored rhyme placement, multi-rhyme bars +- **Bar Structure:** At least 2 internal rhyme events plus optional end rhyme +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Place at least two rhyme events inside most bars. +- Continue at least one internal rhyme family across adjacent bars. +- Vary rhyme position. +- Use slant rhyme where exact rhyme would sound forced. +- Keep syntax natural. + +## Avoid +End-rhyme-only writing, forced alliteration, meaningless rhyme stuffing + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Do most bars rhyme internally before the final word? +- [ ] Do internal patterns continue across bars? +- [ ] Are rhymes natural enough to speak smoothly? +- [ ] Is meaning preserved? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/13_multisyllabic_master.md b/lyric_styles/hiphop_30/13_multisyllabic_master.md new file mode 100644 index 0000000..0b81a5c --- /dev/null +++ b/lyric_styles/hiphop_30/13_multisyllabic_master.md @@ -0,0 +1,70 @@ +# Multisyllabic Master + +## Purpose +Build sophisticated extended rhyme families using multiple syllables while maintaining natural phrasing and meaning. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 10–17 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Extreme +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Advanced but fluent +- **Storytelling Level:** Medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low +- **Flow Variation:** Controlled and technical +- **Preferred Rhyme Schemes:** 3–6 syllable rhyme families sustained over 2–6 bars +- **Bar Structure:** Extended rhyme families with natural sentence flow +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Use multi-syllable rhyme families as primary anchors. +- Sustain key rhyme families for multiple bars. +- Allow near-rhyme when it improves naturalness. +- Match stress patterns, not spelling. +- Keep content coherent. + +## Avoid +Single-syllable rhyme dependence, forced pronunciation, nonsense rhyme phrases + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Are core rhyme anchors at least 2–3 syllables? +- [ ] Do rhyme families continue across several bars? +- [ ] Would pronunciation remain natural? +- [ ] Does meaning stay stronger than rhyme gimmicks? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/14_flow_switcher.md b/lyric_styles/hiphop_30/14_flow_switcher.md new file mode 100644 index 0000000..d485bcd --- /dev/null +++ b/lyric_styles/hiphop_30/14_flow_switcher.md @@ -0,0 +1,69 @@ +# Flow Switcher + +## Purpose +Create verses that deliberately change cadence, syllable count, rhyme placement, and rhythmic pocket several times. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Variable +- **Target Syllables:** 6–18 syllables depending on section +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** Medium-high +- **Wordplay Level:** High +- **Metaphor Density:** Medium +- **Vocabulary:** Adaptive +- **Storytelling Level:** Medium +- **Aggression:** Medium-high +- **Emotional Intensity:** High +- **Repetition:** Low-medium +- **Flow Variation:** Core defining feature: switch every 2–8 bars +- **Preferred Rhyme Schemes:** Changes with each pocket +- **Bar Structure:** Distinct rhythmic sections with deliberate transitions +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Use at least 3 distinct flow pockets in a 16-bar verse. +- Change at least two variables per switch: syllable count, pause placement, rhyme density, or sentence length. +- Signal transitions with a punch, pause, pickup, or repeated phrase. +- Let each pocket establish itself before switching again. + +## Avoid +Random switching without contrast, switching every single bar, losing musical coherence + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can at least 3 different rhythmic pockets be identified? +- [ ] Do switches feel intentional? +- [ ] Does each new pocket contrast with the last? +- [ ] Does the verse remain musically coherent? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/15_staccato_rap.md b/lyric_styles/hiphop_30/15_staccato_rap.md new file mode 100644 index 0000000..812a16f --- /dev/null +++ b/lyric_styles/hiphop_30/15_staccato_rap.md @@ -0,0 +1,70 @@ +# Staccato Rap + +## Purpose +Create clipped, percussive rap using short phrases, hard stops, and rhythmic negative space. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 4–10 syllables per phrase/bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Low-medium +- **Punchline Frequency:** High +- **Wordplay Level:** Medium-high +- **Metaphor Density:** Medium +- **Vocabulary:** Short, hard, concrete +- **Storytelling Level:** Low +- **Aggression:** High +- **Emotional Intensity:** High +- **Repetition:** Medium +- **Flow Variation:** Clipped and syncopated +- **Preferred Rhyme Schemes:** Short couplets, repeated end sounds +- **Bar Structure:** Fragment / stop / fragment / stop +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Use short clauses and deliberate stops. +- Favor one- and two-syllable impact words. +- Leave visible rhythmic space. +- Use repetition as percussion. +- Keep each phrase easy to accent. + +## Avoid +Long run-on sentences, soft phrasing, excessive descriptive clauses + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can the verse be performed with hard stops? +- [ ] Are phrases short enough to hit like percussion? +- [ ] Is negative space preserved? +- [ ] Are repeated words rhythmic rather than redundant? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/16_run_on_flow.md b/lyric_styles/hiphop_30/16_run_on_flow.md new file mode 100644 index 0000000..1bec75b --- /dev/null +++ b/lyric_styles/hiphop_30/16_run_on_flow.md @@ -0,0 +1,70 @@ +# Run-On Flow + +## Purpose +Create continuous thought streams that spill across bar lines while maintaining internal rhyme and momentum. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 12–18 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Fluid, conversational +- **Storytelling Level:** Medium-high +- **Aggression:** Variable +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Continuous enjambment +- **Preferred Rhyme Schemes:** Internal rhyme chains crossing line boundaries +- **Bar Structure:** Sentences span 2–6 bars +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Carry syntax across bar boundaries. +- Use internal rhymes to maintain musical structure. +- Delay sentence resolution for tension. +- End longer thought chains with a strong payoff. +- Keep each run-on sequence coherent. + +## Avoid +Every bar ending as a complete sentence, choppy punctuation, meaningless rambling + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Do sentences regularly cross bar lines? +- [ ] Does momentum remain clear? +- [ ] Are rhyme cues present even without end-stops? +- [ ] Does each long thought eventually resolve? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/17_dark_cinematic.md b/lyric_styles/hiphop_30/17_dark_cinematic.md new file mode 100644 index 0000000..81db9c9 --- /dev/null +++ b/lyric_styles/hiphop_30/17_dark_cinematic.md @@ -0,0 +1,70 @@ +# Dark Cinematic + +## Purpose +Create ominous, visual rap with dramatic tension, environmental detail, and a film-like sense of progression. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Slow-medium +- **Target Syllables:** 8–14 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Low-medium +- **Wordplay Level:** Medium-high +- **Metaphor Density:** High +- **Vocabulary:** Visual, cold, atmospheric +- **Storytelling Level:** High +- **Aggression:** Medium-high +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Measured and dramatic +- **Preferred Rhyme Schemes:** Dark slant rhymes, slow couplets, internal echoes +- **Bar Structure:** Image → tension → escalation → consequence +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Use sensory environmental details. +- Build tension gradually. +- Maintain a consistent visual palette. +- Use metaphor to deepen atmosphere rather than replace it. +- End sections with a reveal, consequence, or ominous image. + +## Avoid +Cheap horror clichés, random gore, overexplaining the mood, generic darkness + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can each section be pictured like a scene? +- [ ] Does tension increase? +- [ ] Is the mood consistent? +- [ ] Are dark elements specific rather than generic? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/18_introspective.md b/lyric_styles/hiphop_30/18_introspective.md new file mode 100644 index 0000000..bfa663f --- /dev/null +++ b/lyric_styles/hiphop_30/18_introspective.md @@ -0,0 +1,70 @@ +# Introspective + +## Purpose +Create emotionally detailed rap centered on reflection, contradiction, memory, ambition, regret, and self-examination. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Low-medium +- **Delivery Speed:** Slow-medium +- **Target Syllables:** 8–15 syllables per bar +- **Rhyme Density:** Medium +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Low +- **Wordplay Level:** Medium +- **Metaphor Density:** High +- **Vocabulary:** Personal and precise +- **Storytelling Level:** High +- **Aggression:** Low-medium +- **Emotional Intensity:** Very high +- **Repetition:** Low-medium +- **Flow Variation:** Natural and reflective +- **Preferred Rhyme Schemes:** Loose rhyme, slant rhyme, occasional multis +- **Bar Structure:** Memory → feeling → contradiction → insight +- **Hook Compatibility:** Very high + +## Mandatory Writing Rules +- Use specific memories or details. +- Show internal contradiction. +- Allow vulnerability without overexplaining. +- Turn observations into insight. +- Use emotional callbacks. + +## Avoid +Generic motivational clichés, empty sadness, melodrama, vague self-help language + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Are emotions grounded in concrete details? +- [ ] Is there an internal conflict? +- [ ] Does the verse reveal something rather than merely state a feeling? +- [ ] Are clichés minimized? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/19_conscious_rap.md b/lyric_styles/hiphop_30/19_conscious_rap.md new file mode 100644 index 0000000..e3beb54 --- /dev/null +++ b/lyric_styles/hiphop_30/19_conscious_rap.md @@ -0,0 +1,70 @@ +# Conscious Rap + +## Purpose +Explore social, cultural, economic, or philosophical ideas through strong arguments, vivid examples, and human-centered writing. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Medium +- **Target Syllables:** 9–16 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Clear, intelligent +- **Storytelling Level:** High +- **Aggression:** Variable +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Measured and articulate +- **Preferred Rhyme Schemes:** Narrative rhyme, argument-based couplets +- **Bar Structure:** Claim → image/example → tension → reflection +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Ground larger ideas in specific human examples. +- Present tension or complexity instead of simple slogans. +- Use imagery and narrative to carry arguments. +- Keep claims internally consistent. +- Favor questions and observations over sermons. + +## Avoid +Lecturing, slogan-only writing, fake statistics, oversimplified morality, preachiness + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does each major idea have an example or image? +- [ ] Is the writing nuanced rather than preachy? +- [ ] Are unsupported factual claims avoided? +- [ ] Does the song remain musical? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/20_braggadocious.md b/lyric_styles/hiphop_30/20_braggadocious.md new file mode 100644 index 0000000..53e13d4 --- /dev/null +++ b/lyric_styles/hiphop_30/20_braggadocious.md @@ -0,0 +1,70 @@ +# Braggadocious + +## Purpose +Create confident, competitive rap built around dominance, status, skill, exaggeration, and quotable flexes. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** High +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 8–14 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** High +- **Wordplay Level:** High +- **Metaphor Density:** Very high +- **Vocabulary:** Bold, vivid +- **Storytelling Level:** Low +- **Aggression:** High +- **Emotional Intensity:** Medium-high +- **Repetition:** Low-medium +- **Flow Variation:** Confident and commanding +- **Preferred Rhyme Schemes:** Couplets, extended flex rhyme chains +- **Bar Structure:** Claim → image/comparison → escalation +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Support boasts with vivid comparisons. +- Escalate imagery rather than repeat the same flex. +- Use technical skill as part of the confidence. +- Make at least one quotable claim every 2 bars. +- Vary status, skill, resilience, and presence as flex categories. + +## Avoid +Generic money/car/jewelry lists, empty boasting, repeated status claims + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Are boasts specific and memorable? +- [ ] Is imagery varied? +- [ ] Does confidence come through rhythm as well as words? +- [ ] Are generic flex clichés minimized? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/21_minimalist_menace.md b/lyric_styles/hiphop_30/21_minimalist_menace.md new file mode 100644 index 0000000..af410b8 --- /dev/null +++ b/lyric_styles/hiphop_30/21_minimalist_menace.md @@ -0,0 +1,70 @@ +# Minimalist Menace + +## Purpose +Create sparse, intimidating rap where short lines, silence, repetition, and understatement carry the weight. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Slow-medium +- **Target Syllables:** 3–9 syllables per bar +- **Rhyme Density:** Low-medium +- **Internal Rhyme Density:** Low-medium +- **Multisyllabic Rhyme Level:** Low +- **Punchline Frequency:** High +- **Wordplay Level:** Medium +- **Metaphor Density:** Low-medium +- **Vocabulary:** Simple, hard, restrained +- **Storytelling Level:** Low +- **Aggression:** High +- **Emotional Intensity:** Cold +- **Repetition:** High but controlled +- **Flow Variation:** Sparse and deliberate +- **Preferred Rhyme Schemes:** Simple rhyme anchors, repetition, sonic motifs +- **Bar Structure:** Short statement → silence → short statement +- **Hook Compatibility:** Very high + +## Mandatory Writing Rules +- Keep most lines short. +- Use repetition strategically. +- Let implication carry more than explanation. +- Prioritize rhythm and silence. +- Use one strong image instead of several weak ones. + +## Avoid +Dense rhyme webs, long explanations, over-describing threats, constant metaphors + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can words be removed without weakening impact? +- [ ] Does silence feel intentional? +- [ ] Is repetition memorable rather than lazy? +- [ ] Does the tone remain controlled? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/22_chaotic_energy.md b/lyric_styles/hiphop_30/22_chaotic_energy.md new file mode 100644 index 0000000..82b61f2 --- /dev/null +++ b/lyric_styles/hiphop_30/22_chaotic_energy.md @@ -0,0 +1,70 @@ +# Chaotic Energy + +## Purpose +Create high-volatility rap with abrupt pivots, wild imagery, ad-libs, and rapid rhythmic changes while preserving intentional structure. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Extreme +- **Delivery Speed:** Variable-fast +- **Target Syllables:** 5–18 syllables per bar +- **Rhyme Density:** High +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** High +- **Wordplay Level:** High +- **Metaphor Density:** Very high +- **Vocabulary:** Unpredictable and vivid +- **Storytelling Level:** Low +- **Aggression:** High +- **Emotional Intensity:** Extreme +- **Repetition:** Medium +- **Flow Variation:** Rapid switches and interruptions +- **Preferred Rhyme Schemes:** Broken schemes, sudden rhyme bursts, repeated sonic motifs +- **Bar Structure:** Burst → pivot → ad-lib → punch +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Change cadence or image direction every 2–4 bars. +- Maintain one recurring sonic or thematic anchor. +- Use controlled interruptions and ad-libs. +- Include sudden short bars after dense bars. +- Keep each pivot connected by sound, emotion, or theme. + +## Avoid +Pure randomness, incoherent nonsense, identical energy throughout, endless ad-libs + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Is chaos structured by a recurring anchor? +- [ ] Do flow changes feel exciting rather than accidental? +- [ ] Are there contrast points? +- [ ] Can the listener still identify the song's identity? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/23_melodic_rap.md b/lyric_styles/hiphop_30/23_melodic_rap.md new file mode 100644 index 0000000..70923fe --- /dev/null +++ b/lyric_styles/hiphop_30/23_melodic_rap.md @@ -0,0 +1,70 @@ +# Melodic Rap + +## Purpose +Create rap lyrics that naturally support melodic phrasing, emotional repetition, and smooth transitions into sung hooks. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Slow-medium +- **Target Syllables:** 6–12 syllables per bar +- **Rhyme Density:** Medium +- **Internal Rhyme Density:** Low-medium +- **Multisyllabic Rhyme Level:** Low-medium +- **Punchline Frequency:** Low +- **Wordplay Level:** Medium +- **Metaphor Density:** Medium-high +- **Vocabulary:** Simple, emotive +- **Storytelling Level:** Medium +- **Aggression:** Low-medium +- **Emotional Intensity:** Very high +- **Repetition:** High +- **Flow Variation:** Smooth and vowel-friendly +- **Preferred Rhyme Schemes:** Simple couplets, repeated rhyme anchors +- **Bar Structure:** Short melodic phrases with open vowels +- **Hook Compatibility:** Extreme + +## Mandatory Writing Rules +- Favor vowel-rich phrases. +- Use repeated emotional anchor lines. +- Keep syntax singable. +- Build verses toward the hook concept. +- Use simple but specific images. + +## Avoid +Overly dense rhyme chains, difficult consonant clusters, overly technical vocabulary + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can key lines be easily sung? +- [ ] Are hooks memorable after one read? +- [ ] Are vowel sounds smooth? +- [ ] Does repetition reinforce emotion? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/24_hook_driven.md b/lyric_styles/hiphop_30/24_hook_driven.md new file mode 100644 index 0000000..f774ed2 --- /dev/null +++ b/lyric_styles/hiphop_30/24_hook_driven.md @@ -0,0 +1,70 @@ +# Hook Driven + +## Purpose +Build the song around a highly memorable central phrase, with verses designed to reinforce and set up the hook. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Variable +- **Delivery Speed:** Variable +- **Target Syllables:** 6–13 syllables per bar +- **Rhyme Density:** Medium +- **Internal Rhyme Density:** Medium +- **Multisyllabic Rhyme Level:** Low-medium +- **Punchline Frequency:** Medium +- **Wordplay Level:** Medium +- **Metaphor Density:** Medium +- **Vocabulary:** Simple and memorable +- **Storytelling Level:** Medium +- **Aggression:** Variable +- **Emotional Intensity:** High +- **Repetition:** Very high in hook, low-medium in verses +- **Flow Variation:** Designed around hook payoff +- **Preferred Rhyme Schemes:** Simple repeatable patterns +- **Bar Structure:** Verse setup → pre-hook lift → repeated hook +- **Hook Compatibility:** Extreme + +## Mandatory Writing Rules +- Define one central hook phrase. +- Repeat or vary that phrase strategically. +- Make verses point toward the hook's idea. +- Use simple rhythmic wording in the chorus. +- Keep hook language easy to remember. + +## Avoid +Complex hooks, too many hook concepts, verses unrelated to refrain + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can the hook be remembered after one reading? +- [ ] Is there only one main hook concept? +- [ ] Do verses reinforce the hook? +- [ ] Is chorus wording simpler than verse wording? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/25_freestyle_feel.md b/lyric_styles/hiphop_30/25_freestyle_feel.md new file mode 100644 index 0000000..eb169c9 --- /dev/null +++ b/lyric_styles/hiphop_30/25_freestyle_feel.md @@ -0,0 +1,70 @@ +# Freestyle Feel + +## Purpose +Create writing that sounds spontaneous, conversational, associative, and alive without becoming sloppy or directionless. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Variable +- **Target Syllables:** 7–15 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** Medium-high +- **Multisyllabic Rhyme Level:** Medium +- **Punchline Frequency:** Medium-high +- **Wordplay Level:** High +- **Metaphor Density:** Medium +- **Vocabulary:** Conversational +- **Storytelling Level:** Low-medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low-medium +- **Flow Variation:** Loose but rhythmic +- **Preferred Rhyme Schemes:** Flexible and changing +- **Bar Structure:** Thought → association → pivot → punch +- **Hook Compatibility:** Low-medium + +## Mandatory Writing Rules +- Use natural speech rhythms. +- Allow topic pivots through word association. +- Keep some imperfect or near rhymes. +- Include spontaneous-feeling asides. +- Maintain an underlying rhythmic pocket. + +## Avoid +Perfectly symmetrical writing, overly polished transitions, incoherent rambling + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does the verse sound like it could be improvised? +- [ ] Are pivots natural? +- [ ] Is polish low enough to feel spontaneous but high enough to remain coherent? +- [ ] Does rhythm survive loose structure? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/26_complex_schemes.md b/lyric_styles/hiphop_30/26_complex_schemes.md new file mode 100644 index 0000000..2108758 --- /dev/null +++ b/lyric_styles/hiphop_30/26_complex_schemes.md @@ -0,0 +1,70 @@ +# Complex Schemes + +## Purpose +Create intentionally engineered rhyme architecture using extended, nested, mirrored, and changing schemes. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium-high +- **Delivery Speed:** Medium-fast +- **Target Syllables:** 10–17 syllables per bar +- **Rhyme Density:** Very high +- **Internal Rhyme Density:** Very high +- **Multisyllabic Rhyme Level:** Very high +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** Medium-high +- **Vocabulary:** Advanced but natural +- **Storytelling Level:** Medium +- **Aggression:** Variable +- **Emotional Intensity:** Medium +- **Repetition:** Low +- **Flow Variation:** Technical but musical +- **Preferred Rhyme Schemes:** ABAB, AAAA, AABB, nested A1/A2 internals, alternating families +- **Bar Structure:** Designed rhyme map across 4–8 bars +- **Hook Compatibility:** Low-medium + +## Mandatory Writing Rules +- Plan a rhyme architecture before generating each section. +- Use at least two active rhyme families in an 8-bar block. +- Include internal and end-rhyme interplay. +- Change scheme deliberately at section boundaries. +- Preserve sentence clarity. + +## Avoid +Random rhyme accumulation, schemes that obscure meaning, forced syntax + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can the rhyme scheme be mapped clearly? +- [ ] Does the architecture continue beyond 2 bars? +- [ ] Are transitions between schemes intentional? +- [ ] Does meaning remain natural? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/27_double_time_technical.md b/lyric_styles/hiphop_30/27_double_time_technical.md new file mode 100644 index 0000000..2322af1 --- /dev/null +++ b/lyric_styles/hiphop_30/27_double_time_technical.md @@ -0,0 +1,70 @@ +# Double-Time Technical + +## Purpose +Create very fast but highly controlled rap with consistent syllable counts, dense internal rhyme, and disciplined rhythmic pockets. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Very high +- **Delivery Speed:** Double-time +- **Target Syllables:** 13–19 syllables per bar +- **Rhyme Density:** Very high +- **Internal Rhyme Density:** Very high +- **Multisyllabic Rhyme Level:** High +- **Punchline Frequency:** Medium-high +- **Wordplay Level:** High +- **Metaphor Density:** Medium +- **Vocabulary:** Compact and technical +- **Storytelling Level:** Low-medium +- **Aggression:** High +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Tightly metered double-time +- **Preferred Rhyme Schemes:** Internal multis, repeated triplet or 16th-note pockets +- **Bar Structure:** Consistent syllable grids with controlled variation +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Keep adjacent bars within a narrow syllable range. +- Use internal rhymes as timing anchors. +- Break long words across natural stress groups. +- Insert occasional breath/reset bars. +- Maintain semantic clarity at speed. + +## Avoid +Unperformable tongue-twisters, huge syllable swings, filler words used for meter + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Are syllable counts reasonably consistent? +- [ ] Can the bars be delivered quickly without unnatural stress? +- [ ] Do internal rhymes support timing? +- [ ] Are breath points available? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/28_slow_heavy_bars.md b/lyric_styles/hiphop_30/28_slow_heavy_bars.md new file mode 100644 index 0000000..4941fa5 --- /dev/null +++ b/lyric_styles/hiphop_30/28_slow_heavy_bars.md @@ -0,0 +1,70 @@ +# Slow Heavy Bars + +## Purpose +Create deliberate, weighty rap where fewer words carry more meaning and each line is designed to linger. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Slow +- **Target Syllables:** 5–11 syllables per bar +- **Rhyme Density:** Low-medium +- **Internal Rhyme Density:** Low-medium +- **Multisyllabic Rhyme Level:** Low-medium +- **Punchline Frequency:** High +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Sparse, precise +- **Storytelling Level:** Medium +- **Aggression:** Medium-high +- **Emotional Intensity:** High +- **Repetition:** Low +- **Flow Variation:** Slow, deliberate, spacious +- **Preferred Rhyme Schemes:** Simple powerful rhyme anchors +- **Bar Structure:** Statement → pause → consequence +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Keep bars concise. +- Make each line carry a clear image, claim, or consequence. +- Use silence and space as part of the rhythm. +- Favor strong nouns and verbs. +- End sections with quotable lines. + +## Avoid +Overwriting, filler adjectives, dense internal rhymes, rushed ideas + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Does every bar earn its place? +- [ ] Can any unnecessary word be removed? +- [ ] Are impact lines given room? +- [ ] Does the verse feel heavy rather than empty? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/29_psychedelic_rap.md b/lyric_styles/hiphop_30/29_psychedelic_rap.md new file mode 100644 index 0000000..eba7259 --- /dev/null +++ b/lyric_styles/hiphop_30/29_psychedelic_rap.md @@ -0,0 +1,70 @@ +# Psychedelic Rap + +## Purpose +Create dreamlike, surreal rap using altered perception, sensory fusion, impossible imagery, and fluid associative transitions. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Medium +- **Delivery Speed:** Variable +- **Target Syllables:** 8–16 syllables per bar +- **Rhyme Density:** Medium-high +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Medium-high +- **Punchline Frequency:** Low-medium +- **Wordplay Level:** Very high +- **Metaphor Density:** Extreme +- **Vocabulary:** Surreal, colorful, sensory +- **Storytelling Level:** Low-medium +- **Aggression:** Low-medium +- **Emotional Intensity:** High +- **Repetition:** Medium +- **Flow Variation:** Fluid and shape-shifting +- **Preferred Rhyme Schemes:** Slant rhymes, echo rhymes, internal waves +- **Bar Structure:** Image → mutation → association → return +- **Hook Compatibility:** High + +## Mandatory Writing Rules +- Blend senses and categories in imagery. +- Transform one image into another rather than jumping randomly. +- Use recurring motifs to create coherence. +- Favor dream logic over literal explanation. +- Use sonic texture in word choice. + +## Avoid +Random nonsense, drug clichés as the only concept, disconnected surreal images + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Do surreal images connect through transformation or motif? +- [ ] Is the language sensory? +- [ ] Does the verse have an identifiable emotional center? +- [ ] Are clichés minimized? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/lyric_styles/hiphop_30/30_experimental_flow.md b/lyric_styles/hiphop_30/30_experimental_flow.md new file mode 100644 index 0000000..f5f2cd5 --- /dev/null +++ b/lyric_styles/hiphop_30/30_experimental_flow.md @@ -0,0 +1,70 @@ +# Experimental Flow + +## Purpose +Break normal rap conventions deliberately through irregular bar lengths, unusual pauses, asymmetrical rhyme placement, and unconventional phrasing. + +## Style Lock +When this style is selected, **do not merely imitate the mood**. The generated lyrics must visibly satisfy the structural and linguistic rules below. If the draft fails the self-check, rewrite it before returning the final lyrics. + +## Core Profile +- **Energy:** Variable +- **Delivery Speed:** Variable +- **Target Syllables:** 3–20 syllables depending on section +- **Rhyme Density:** Variable-high +- **Internal Rhyme Density:** High +- **Multisyllabic Rhyme Level:** Variable +- **Punchline Frequency:** Medium +- **Wordplay Level:** High +- **Metaphor Density:** High +- **Vocabulary:** Unrestricted but intentional +- **Storytelling Level:** Variable +- **Aggression:** Variable +- **Emotional Intensity:** High +- **Repetition:** Variable +- **Flow Variation:** Irregular by design +- **Preferred Rhyme Schemes:** Broken rhyme maps, delayed rhyme resolution, nonstandard repetition +- **Bar Structure:** Asymmetrical; contrast is essential +- **Hook Compatibility:** Medium + +## Mandatory Writing Rules +- Break at least two conventional expectations per section. +- Use contrast between dense and sparse lines. +- Delay or displace rhyme resolution. +- Use punctuation and spacing to imply unusual timing. +- Maintain one unifying concept or sonic device. + +## Avoid +Randomness without rationale, unreadable structure, unconventional choices that do not change the listening experience + +## Generation Procedure +1. Decide the section purpose before writing: verse, hook, bridge, intro, or outro. +2. Establish a rhythmic pocket that matches this style. +3. Draft the lyrics using the target syllable range and rhyme behavior above. +4. Strengthen weak end words, internal rhyme positions, and rhythmic accents. +5. Remove filler and any line that does not support the style objective. +6. Run the **Style Compliance Check** below. +7. Rewrite failed lines before producing the final result. + +## Style Compliance Check +- [ ] Can the experimental choices be identified? +- [ ] Do they change cadence or musical feel? +- [ ] Is there still a unifying identity? +- [ ] Does unconventional structure remain performable? + +## Failure Conditions +The output should be considered **off-style** and regenerated if: +- The defining cadence or rhyme behavior is missing. +- More than roughly 25% of the bars ignore the target structure. +- Filler lines are used to reach length. +- The vocabulary, emotional tone, or rhyme density drifts into a different preset. +- The generator describes the style instead of actually writing in it. + +## App Instruction +When this preset is active, treat these rules as a **hard style constraint**. Content prompts may change the subject, setting, story, mood, or perspective, but they should not override the core rhythmic and lyrical behavior unless the user explicitly disables this style. + +## Combination Behavior +If combined with another preset: +- Preserve this style's strongest defining traits. +- Merge compatible attributes rather than averaging everything into a generic midpoint. +- If two rules conflict, prioritize the user's explicitly selected primary style. +- Never allow combination mode to remove all defining features of this preset. diff --git a/music_styles/001_boom_bap.md b/music_styles/001_boom_bap.md new file mode 100644 index 0000000..1d38fd2 --- /dev/null +++ b/music_styles/001_boom_bap.md @@ -0,0 +1,36 @@ +# Boom Bap + +**Family:** Classic / Sample-Based +**Typical tempo:** 82–96 BPM + +## Core Identity + +Classic sample-driven hip-hop built around hard kick/snare interplay, swung groove, chopped musical fragments, and a strong pocket for rapping. + +## Rhythm & Drums + +Punchy kick, cracking snare, dusty hats, light swing; drums should feel human rather than grid-perfect. + +## Bass & Low End + +Warm sampled bass, upright/electric bass fragments, or simple sub reinforcement. + +## Harmony, Melody & Sound Palette + +Chopped soul, jazz, funk, or soundtrack material; filtered loops, stabs, scratches, vinyl texture. + +## Vocal / Rap Approach + +Bar-focused MC delivery; clear pocket, internal rhyme space, minimal melodic dependence. + +## Arrangement + +Loop-centered verses with subtle sample variation, drops, fills, and a stronger hook section. + +## Mood & Energy + +Head-nod, grounded, confident, raw. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/002_golden_era_hip_hop.md b/music_styles/002_golden_era_hip_hop.md new file mode 100644 index 0000000..5760734 --- /dev/null +++ b/music_styles/002_golden_era_hip_hop.md @@ -0,0 +1,32 @@ +# Golden Era Hip-Hop + +**Family:** Classic / Sample-Based +**Typical tempo:** 88–108 BPM + +## Core Identity + +Late-1980s to early-1990s hip-hop language: breakbeats, funk-derived samples, direct MC performance, DJ culture, and memorable rhythmic hooks. + +## Rhythm & Drums + +Breakbeat-led, lively hats, snare-forward backbeat, occasional percussion loops and cuts. + +## Bass & Low End + +Funk or sampled basslines with clear movement. + +## Harmony, Melody & Sound Palette + +Funk, soul, jazz, horn hits, scratches, vocal snippets, simple melodic loops. + +## Vocal / Rap Approach + +Direct, rhythmic, charismatic; call-and-response and crew energy work well. + +## Arrangement + +Clear intro/verse/hook structure with DJ breaks and short transitions. + +## Mood & Energy + +Energetic, streetwise, celebratory, foundational. diff --git a/music_styles/003_underground_hip_hop.md b/music_styles/003_underground_hip_hop.md new file mode 100644 index 0000000..03039d0 --- /dev/null +++ b/music_styles/003_underground_hip_hop.md @@ -0,0 +1,32 @@ +# Underground Hip-Hop + +**Family:** Underground / Alternative +**Typical tempo:** 75–96 BPM + +## Core Identity + +Independent-minded hip-hop prioritizing character, lyrical depth, unusual samples, and less-polished textures over mainstream formulas. + +## Rhythm & Drums + +Dry, gritty, sometimes deliberately uneven; drums can be sparse or unusually layered. + +## Bass & Low End + +Muted sub, sampled bass, or dirty low-end loop. + +## Harmony, Melody & Sound Palette + +Obscure samples, degraded textures, eerie keys, dusty jazz, field recordings, unconventional chops. + +## Vocal / Rap Approach + +Dense writing, abstract imagery, technical or introspective delivery. + +## Arrangement + +Longer verses, less predictable hooks, beat switches or sample evolutions. + +## Mood & Energy + +Raw, cerebral, personal, uncompromising. diff --git a/music_styles/004_lo_fi_hip_hop.md b/music_styles/004_lo_fi_hip_hop.md new file mode 100644 index 0000000..0b22890 --- /dev/null +++ b/music_styles/004_lo_fi_hip_hop.md @@ -0,0 +1,36 @@ +# Lo-Fi Hip-Hop + +**Family:** Lo-Fi / Chill +**Typical tempo:** 65–90 BPM + +## Core Identity + +Dusty, intimate hip-hop with softened transients, tape/vinyl wear, mellow harmony, and relaxed repetition. + +## Rhythm & Drums + +Soft kicks, brushed or muted snares, lazy hats, noticeable swing. + +## Bass & Low End + +Rounded bass with limited sub aggression. + +## Harmony, Melody & Sound Palette + +Jazz chords, Rhodes, guitar, piano, vinyl noise, wow/flutter, filtered samples. + +## Vocal / Rap Approach + +Usually restrained rap, spoken phrases, or instrumental focus. + +## Arrangement + +Short loop cycles with gentle variation; avoid dramatic drops. + +## Mood & Energy + +Warm, nostalgic, calm, late-night. + +## Performance Detail + +Use degradation selectively. The mix can sound worn without becoming muddy; preserve a readable kick, snare, and vocal range. diff --git a/music_styles/005_jazz_rap.md b/music_styles/005_jazz_rap.md new file mode 100644 index 0000000..c7a702c --- /dev/null +++ b/music_styles/005_jazz_rap.md @@ -0,0 +1,32 @@ +# Jazz Rap + +**Family:** Jazz / Soul +**Typical tempo:** 78–100 BPM + +## Core Identity + +Hip-hop built around jazz harmony, improvisational textures, upright or electric bass, and articulate rhythmic rapping. + +## Rhythm & Drums + +Boom-bap or brushed grooves; syncopated percussion can add live feel. + +## Bass & Low End + +Walking or melodic basslines, often more active than standard hip-hop. + +## Harmony, Melody & Sound Palette + +Extended chords, sax, trumpet, Rhodes, vibraphone, piano, jazz guitar. + +## Vocal / Rap Approach + +Conversational, intelligent, elastic flow; leave space for instrumentation. + +## Arrangement + +Verse/hook form with instrumental interludes, solos, or evolving comping. + +## Mood & Energy + +Sophisticated, cool, reflective, urban. diff --git a/music_styles/006_conscious_hip_hop.md b/music_styles/006_conscious_hip_hop.md new file mode 100644 index 0000000..34e942d --- /dev/null +++ b/music_styles/006_conscious_hip_hop.md @@ -0,0 +1,36 @@ +# Conscious Hip-Hop + +**Family:** Lyrical / Message +**Typical tempo:** 72–98 BPM + +## Core Identity + +Message-centered rap where production supports clarity, reflection, social commentary, personal growth, or philosophical themes. + +## Rhythm & Drums + +Supportive rather than overpowering; clean boom-bap, soul, or modern drums. + +## Bass & Low End + +Stable, musical low end that leaves vocal room. + +## Harmony, Melody & Sound Palette + +Soul, piano, strings, restrained samples, atmospheric pads. + +## Vocal / Rap Approach + +Highly intelligible, emotionally controlled, lyric-forward delivery. + +## Arrangement + +Verses carry narrative/argument; hooks summarize emotional or thematic center. + +## Mood & Energy + +Reflective, purposeful, humane, serious. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/007_abstract_hip_hop.md b/music_styles/007_abstract_hip_hop.md new file mode 100644 index 0000000..0936849 --- /dev/null +++ b/music_styles/007_abstract_hip_hop.md @@ -0,0 +1,36 @@ +# Abstract Hip-Hop + +**Family:** Experimental / Alternative +**Typical tempo:** 65–100 BPM + +## Core Identity + +Non-literal, fragmented, or surreal hip-hop using unconventional rhythm, sound selection, and lyrical structure. + +## Rhythm & Drums + +Off-kilter placement, unusual percussion, abrupt silence, asymmetrical patterns. + +## Bass & Low End + +Can be minimal, distorted, unstable, or textural rather than melodic. + +## Harmony, Melody & Sound Palette + +Micro-samples, noise, detuned keys, strange synths, collage techniques. + +## Vocal / Rap Approach + +Associative imagery, unusual cadence, broken phrasing, spoken or deadpan delivery. + +## Arrangement + +Nonstandard sections, abrupt transitions, short loops, deliberate discontinuity. + +## Mood & Energy + +Surreal, cerebral, uneasy, inventive. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/008_alternative_hip_hop.md b/music_styles/008_alternative_hip_hop.md new file mode 100644 index 0000000..5c23b5a --- /dev/null +++ b/music_styles/008_alternative_hip_hop.md @@ -0,0 +1,36 @@ +# Alternative Hip-Hop + +**Family:** Experimental / Alternative +**Typical tempo:** 70–110 BPM + +## Core Identity + +Broad genre-crossing hip-hop that avoids one fixed formula, combining rap with indie, electronic, rock, soul, jazz, or art-pop ideas. + +## Rhythm & Drums + +Can range from organic breakbeats to electronic kits; prioritize distinctive groove. + +## Bass & Low End + +Bass should fit the hybrid palette rather than default to 808s. + +## Harmony, Melody & Sound Palette + +Unusual instruments, genre hybrids, left-field harmony, creative processing. + +## Vocal / Rap Approach + +Flexible: melodic rap, spoken delivery, technical bars, or mixed vocal forms. + +## Arrangement + +More songlike or experimental structures; bridges and contrast sections encouraged. + +## Mood & Energy + +Individualistic, adventurous, expressive. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/009_backpack_rap.md b/music_styles/009_backpack_rap.md new file mode 100644 index 0000000..d156d94 --- /dev/null +++ b/music_styles/009_backpack_rap.md @@ -0,0 +1,36 @@ +# Backpack Rap + +**Family:** Underground / Lyrical +**Typical tempo:** 80–96 BPM + +## Core Identity + +Lyric-centered underground rap associated with crate-digging production, clever writing, and a deliberately non-commercial feel. + +## Rhythm & Drums + +Dusty boom-bap, crisp snare, swung hats. + +## Bass & Low End + +Sampled or warm electric bass. + +## Harmony, Melody & Sound Palette + +Soul/jazz chops, obscure loops, scratches, simple melodic fragments. + +## Vocal / Rap Approach + +Dense bars, wordplay, storytelling, technical rhyme schemes. + +## Arrangement + +Long verses, modest hooks, DJ-style transitions. + +## Mood & Energy + +Thoughtful, witty, grounded, underground. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/010_hardcore_hip_hop.md b/music_styles/010_hardcore_hip_hop.md new file mode 100644 index 0000000..daaf5fb --- /dev/null +++ b/music_styles/010_hardcore_hip_hop.md @@ -0,0 +1,32 @@ +# Hardcore Hip-Hop + +**Family:** Hard / Street +**Typical tempo:** 78–102 BPM + +## Core Identity + +Aggressive hip-hop emphasizing forceful drums, confrontational energy, dense low end, and commanding vocal presence. + +## Rhythm & Drums + +Hard kicks, sharp snares, heavy percussion, minimal softness. + +## Bass & Low End + +Thick bass or sub with aggressive envelope. + +## Harmony, Melody & Sound Palette + +Dark samples, minor keys, stabs, sirens, tense strings, distorted layers. + +## Vocal / Rap Approach + +Forceful projection, clipped phrasing, high conviction. + +## Arrangement + +Strong verse/hook contrast, breakdowns, dramatic stops. + +## Mood & Energy + +Intense, confrontational, muscular. diff --git a/music_styles/011_gangsta_rap.md b/music_styles/011_gangsta_rap.md new file mode 100644 index 0000000..74b8323 --- /dev/null +++ b/music_styles/011_gangsta_rap.md @@ -0,0 +1,32 @@ +# Gangsta Rap + +**Family:** Hard / Street +**Typical tempo:** 75–100 BPM + +## Core Identity + +Street-narrative hip-hop focused on realism, tension, power, consequence, and cinematic urban storytelling. + +## Rhythm & Drums + +Heavy but spacious; snare and kick should support narrative cadence. + +## Bass & Low End + +Deep bass, funk bass, or restrained 808 depending era. + +## Harmony, Melody & Sound Palette + +Funk, soul, ominous keys, strings, synths, ambient street textures. + +## Vocal / Rap Approach + +Calm menace, detailed storytelling, direct speech, controlled intensity. + +## Arrangement + +Narrative verses, memorable hooks, instrumental breathing room. + +## Mood & Energy + +Serious, cinematic, tense, streetwise. diff --git a/music_styles/012_g_funk.md b/music_styles/012_g_funk.md new file mode 100644 index 0000000..925b103 --- /dev/null +++ b/music_styles/012_g_funk.md @@ -0,0 +1,32 @@ +# G-Funk + +**Family:** West Coast +**Typical tempo:** 82–100 BPM + +## Core Identity + +West Coast funk-derived hip-hop with elastic bass, bright synth leads, relaxed drums, and spacious melodic grooves. + +## Rhythm & Drums + +Laid-back swing, clap/snare backbeat, crisp hats, funk percussion. + +## Bass & Low End + +Prominent rubbery synth or electric bassline. + +## Harmony, Melody & Sound Palette + +Whining synth leads, Parliament-style funk colors, electric piano, talkbox-like textures. + +## Vocal / Rap Approach + +Smooth, relaxed, charismatic delivery; melodic hooks fit naturally. + +## Arrangement + +Extended grooves, instrumental intros/outros, hook-heavy structure. + +## Mood & Energy + +Sunny, cruising, confident, smooth. diff --git a/music_styles/013_west_coast_hip_hop.md b/music_styles/013_west_coast_hip_hop.md new file mode 100644 index 0000000..802df4e --- /dev/null +++ b/music_styles/013_west_coast_hip_hop.md @@ -0,0 +1,32 @@ +# West Coast Hip-Hop + +**Family:** Regional +**Typical tempo:** 80–102 BPM + +## Core Identity + +Broad West Coast sound emphasizing funk influence, spacious mixes, clear basslines, relaxed-to-hard drum grooves, and cinematic polish. + +## Rhythm & Drums + +Clean, open drums with strong backbeat and bounce. + +## Bass & Low End + +Defined bassline or sub; often more melodic than East Coast approaches. + +## Harmony, Melody & Sound Palette + +Funk synths, pianos, strings, guitars, bells, atmospheric pads. + +## Vocal / Rap Approach + +Rhythmic, confident, often conversational delivery. + +## Arrangement + +Strong hooks, roomy verses, occasional instrumental breaks. + +## Mood & Energy + +Cruising, confident, polished, streetwise. diff --git a/music_styles/014_east_coast_hip_hop.md b/music_styles/014_east_coast_hip_hop.md new file mode 100644 index 0000000..64b724b --- /dev/null +++ b/music_styles/014_east_coast_hip_hop.md @@ -0,0 +1,36 @@ +# East Coast Hip-Hop + +**Family:** Regional +**Typical tempo:** 78–98 BPM + +## Core Identity + +Dense, rhythm-first hip-hop associated with chopped samples, hard drums, lyrical emphasis, and gritty urban atmosphere. + +## Rhythm & Drums + +Punchy boom-bap, sharp snares, compact swing, layered breaks. + +## Bass & Low End + +Sampled bass, dark low-end loops, controlled sub. + +## Harmony, Melody & Sound Palette + +Soul/jazz chops, piano stabs, horns, strings, eerie samples. + +## Vocal / Rap Approach + +Bar-heavy delivery with tight rhyme placement. + +## Arrangement + +Loop-focused verses, concise hooks, DJ cuts or sample drops. + +## Mood & Energy + +Gritty, focused, nocturnal, lyrical. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/015_southern_hip_hop.md b/music_styles/015_southern_hip_hop.md new file mode 100644 index 0000000..03fffd5 --- /dev/null +++ b/music_styles/015_southern_hip_hop.md @@ -0,0 +1,32 @@ +# Southern Hip-Hop + +**Family:** Regional +**Typical tempo:** 65–95 BPM or double-time feel + +## Core Identity + +Broad Southern rap language built on heavy low end, strong rhythmic identity, regional bounce, and flexible tempos. + +## Rhythm & Drums + +808-forward, rolling hats, claps, syncopated percussion, bounce variations. + +## Bass & Low End + +Deep sub and long 808 notes; bass can carry melodic movement. + +## Harmony, Melody & Sound Palette + +Sparse synths, bells, pianos, soul elements, atmospheric motifs. + +## Vocal / Rap Approach + +Flexible cadence, drawl-friendly pocket, rhythmic repetition, melodic hooks. + +## Arrangement + +Hook-forward with clear drops and energetic transitions. + +## Mood & Energy + +Heavy, confident, hypnotic, regional. diff --git a/music_styles/016_dirty_south.md b/music_styles/016_dirty_south.md new file mode 100644 index 0000000..889f4a7 --- /dev/null +++ b/music_styles/016_dirty_south.md @@ -0,0 +1,32 @@ +# Dirty South + +**Family:** Southern / Street +**Typical tempo:** 70–100 BPM + +## Core Identity + +Raw Southern hip-hop emphasizing booming bass, chant energy, aggressive percussion, and club/street impact. + +## Rhythm & Drums + +Hard claps/snares, rolling hats, stomping kicks, syncopated percussion. + +## Bass & Low End + +Large sub or 808 with simple commanding movement. + +## Harmony, Melody & Sound Palette + +Dark synths, brass stabs, bells, minimal loops. + +## Vocal / Rap Approach + +Bold, repetitive, chant-ready delivery with strong rhythmic phrasing. + +## Arrangement + +Big hooks, call-and-response, breaks for crowd energy. + +## Mood & Energy + +Rowdy, forceful, bass-heavy. diff --git a/music_styles/017_memphis_rap.md b/music_styles/017_memphis_rap.md new file mode 100644 index 0000000..6d4c89f --- /dev/null +++ b/music_styles/017_memphis_rap.md @@ -0,0 +1,32 @@ +# Memphis Rap + +**Family:** Southern / Dark +**Typical tempo:** 70–95 BPM + +## Core Identity + +Dark, hypnotic Southern rap rooted in raw drum-machine patterns, eerie samples, repetitive motifs, and lo-fi menace. + +## Rhythm & Drums + +Dry drum-machine hits, sharp snares, rapid hats, repetitive patterns. + +## Bass & Low End + +Distorted or simple sub-bass; low end can feel rough and narrow. + +## Harmony, Melody & Sound Palette + +Horror-film samples, minor piano, cowbells, vocal chops, tape degradation. + +## Vocal / Rap Approach + +Repetitive, incantatory, laid-back or menacing flows. + +## Arrangement + +Short loops, sparse arrangement, recurring vocal/sample motifs. + +## Mood & Energy + +Sinister, hypnotic, nocturnal, raw. diff --git a/music_styles/018_houston_rap.md b/music_styles/018_houston_rap.md new file mode 100644 index 0000000..8b95083 --- /dev/null +++ b/music_styles/018_houston_rap.md @@ -0,0 +1,32 @@ +# Houston Rap + +**Family:** Southern / Regional +**Typical tempo:** 60–85 BPM + +## Core Identity + +Slow, spacious Southern hip-hop with deep bass, relaxed cadence, soulful atmosphere, and room for chopped-and-screwed influence. + +## Rhythm & Drums + +Slow rolling drums, crisp claps, loose hats. + +## Bass & Low End + +Deep sustained sub, warm bass, occasionally melodic slides. + +## Harmony, Melody & Sound Palette + +Soulful samples, synth pads, piano, syrupy textures. + +## Vocal / Rap Approach + +Drawn-out cadence, conversational flow, melodic phrases. + +## Arrangement + +Long grooves and spacious sections; hooks can stretch. + +## Mood & Energy + +Heavy, smooth, late-night, luxurious. diff --git a/music_styles/019_chopped_and_screwed.md b/music_styles/019_chopped_and_screwed.md new file mode 100644 index 0000000..d525b8c --- /dev/null +++ b/music_styles/019_chopped_and_screwed.md @@ -0,0 +1,36 @@ +# Chopped & Screwed + +**Family:** Southern / Experimental +**Typical tempo:** 45–70 BPM perceived + +## Core Identity + +A slow, psychedelic remix aesthetic built from dramatically reduced tempo, repeated fragments, pitch shifts, and stuttered edits. + +## Rhythm & Drums + +Original groove slowed; edits and retriggers become part of rhythm. + +## Bass & Low End + +Pitch-lowered low end, long sub tails, thickened bass texture. + +## Harmony, Melody & Sound Palette + +Stretched samples, tape-like drag, repeated words, abrupt rewind effects. + +## Vocal / Rap Approach + +Vocals pitched down and extended; phrases can repeat rhythmically. + +## Arrangement + +Nonlinear remix structure with cuts, repeats, drops, and slowed transitions. + +## Mood & Energy + +Dazed, heavy, hypnotic, dreamlike. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/020_crunk.md b/music_styles/020_crunk.md new file mode 100644 index 0000000..0fbe2c7 --- /dev/null +++ b/music_styles/020_crunk.md @@ -0,0 +1,36 @@ +# Crunk + +**Family:** Southern / Club +**Typical tempo:** 70–90 BPM or double-time + +## Core Identity + +High-energy Southern club rap driven by shouted hooks, aggressive drums, repetitive synth motifs, and crowd-response dynamics. + +## Rhythm & Drums + +Huge kicks, claps, rapid hats, energetic percussion. + +## Bass & Low End + +Large 808/sub hits with simple patterns. + +## Harmony, Melody & Sound Palette + +Aggressive synth stabs, sirens, brass-like patches, minimal harmony. + +## Vocal / Rap Approach + +Shouted, chant-heavy, call-and-response vocals. + +## Arrangement + +Short verses, huge repeated hooks, breakdowns and drops. + +## Mood & Energy + +Explosive, rowdy, physical, communal. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/021_bounce.md b/music_styles/021_bounce.md new file mode 100644 index 0000000..093e87a --- /dev/null +++ b/music_styles/021_bounce.md @@ -0,0 +1,36 @@ +# Bounce + +**Family:** Southern / Club +**Typical tempo:** 95–115 BPM + +## Core Identity + +New Orleans-rooted dance rap with fast, repetitive rhythms, call-and-response vocals, and syncopated party energy. + +## Rhythm & Drums + +Rapid kick patterns, claps, repetitive percussion loops. + +## Bass & Low End + +Simple sub or bass pulse supporting the rhythm. + +## Harmony, Melody & Sound Palette + +Minimal melodic loops, vocal samples, whistles, bright stabs. + +## Vocal / Rap Approach + +Call-and-response, chants, repeated phrases, energetic MCing. + +## Arrangement + +Loop-driven, repetitive, built for continuous movement. + +## Mood & Energy + +Celebratory, kinetic, playful, high-energy. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/022_trap.md b/music_styles/022_trap.md new file mode 100644 index 0000000..59f1e50 --- /dev/null +++ b/music_styles/022_trap.md @@ -0,0 +1,36 @@ +# Trap + +**Family:** Trap +**Typical tempo:** 120–160 BPM with half-time feel + +## Core Identity + +Modern hip-hop centered on 808 bass, rolling hi-hats, sparse melodic loops, and strong rhythmic negative space. + +## Rhythm & Drums + +Punchy kick, clap/snare on half-time backbeat, hat rolls, triplets, open-hat accents. + +## Bass & Low End + +Long 808s with slides, pitch movement, and strong sub presence. + +## Harmony, Melody & Sound Palette + +Bells, plucks, pianos, pads, short minor-key motifs. + +## Vocal / Rap Approach + +Rhythmic pocketing, triplet flows, melodic phrases or clipped delivery. + +## Arrangement + +Intro, hook, verse, hook with drops, mutes, risers, beat changes. + +## Mood & Energy + +Dark-to-polished, spacious, hard-hitting. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/023_dark_trap.md b/music_styles/023_dark_trap.md new file mode 100644 index 0000000..931993a --- /dev/null +++ b/music_styles/023_dark_trap.md @@ -0,0 +1,36 @@ +# Dark Trap + +**Family:** Trap / Dark +**Typical tempo:** 120–155 BPM + +## Core Identity + +Trap with ominous harmony, cinematic tension, distorted low end, and sparse threatening sound design. + +## Rhythm & Drums + +Hard transient drums, controlled hat rolls, dramatic pauses. + +## Bass & Low End + +Heavy distorted 808s, slides, sustained sub pressure. + +## Harmony, Melody & Sound Palette + +Minor/Phrygian colors, bells, choirs, reversed textures, dark pads. + +## Vocal / Rap Approach + +Low-register, restrained, threatening or emotionally cold delivery. + +## Arrangement + +Tension-building intros, hard drops, sparse verses, dramatic transitions. + +## Mood & Energy + +Menacing, nocturnal, cinematic, severe. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/024_melodic_trap.md b/music_styles/024_melodic_trap.md new file mode 100644 index 0000000..3fc646d --- /dev/null +++ b/music_styles/024_melodic_trap.md @@ -0,0 +1,36 @@ +# Melodic Trap + +**Family:** Trap / Melodic +**Typical tempo:** 120–155 BPM + +## Core Identity + +Trap production shaped around memorable melodies, emotional chord progressions, sung-rap phrasing, and smooth 808 movement. + +## Rhythm & Drums + +Cleaner trap drums with less abrasive attack. + +## Bass & Low End + +Warm or gliding 808 that follows harmonic movement. + +## Harmony, Melody & Sound Palette + +Guitar, piano, plucks, pads, airy synths, emotional motifs. + +## Vocal / Rap Approach + +Sung-rap, harmonized hooks, flexible pitch, intimate delivery. + +## Arrangement + +Hook-centric songwriting, bridges, vocal layers, instrumental lifts. + +## Mood & Energy + +Emotional, atmospheric, polished, bittersweet. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/025_street_trap.md b/music_styles/025_street_trap.md new file mode 100644 index 0000000..f3d9f82 --- /dev/null +++ b/music_styles/025_street_trap.md @@ -0,0 +1,36 @@ +# Street Trap + +**Family:** Trap / Street +**Typical tempo:** 125–155 BPM + +## Core Identity + +Hard, minimal trap focused on immediacy, street narrative, aggressive low end, and direct vocal presence. + +## Rhythm & Drums + +Dry punchy drums, sharp hats, sparse fills. + +## Bass & Low End + +Dominant 808, often short and punchy with occasional slides. + +## Harmony, Melody & Sound Palette + +Minimal piano, bells, dark pads, simple repeating motifs. + +## Vocal / Rap Approach + +Direct, rhythmically assertive, less melodic than melodic trap. + +## Arrangement + +Strong hooks, stripped verses, occasional beat cuts for emphasis. + +## Mood & Energy + +Cold, hard, direct, tense. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/026_cloud_rap.md b/music_styles/026_cloud_rap.md new file mode 100644 index 0000000..9cbb890 --- /dev/null +++ b/music_styles/026_cloud_rap.md @@ -0,0 +1,32 @@ +# Cloud Rap + +**Family:** Atmospheric +**Typical tempo:** 70–140 BPM depending drum feel + +## Core Identity + +Dreamlike hip-hop using washed textures, airy pads, soft drums, and impressionistic vocals. + +## Rhythm & Drums + +Soft trap or lo-fi drums, smeared transients, airy hats. + +## Bass & Low End + +Rounded sub or floating 808, usually not overly aggressive. + +## Harmony, Melody & Sound Palette + +Reverb-heavy pads, dream synths, vocal textures, shimmering samples. + +## Vocal / Rap Approach + +Mumbled, melodic, detached, or softly layered delivery. + +## Arrangement + +Long atmospheric intros/outros, simple repeated sections. + +## Mood & Energy + +Ethereal, hazy, introspective, weightless. diff --git a/music_styles/027_plugg.md b/music_styles/027_plugg.md new file mode 100644 index 0000000..9c331c0 --- /dev/null +++ b/music_styles/027_plugg.md @@ -0,0 +1,36 @@ +# Plugg + +**Family:** Trap / Internet +**Typical tempo:** 125–155 BPM + +## Core Identity + +Bright, minimal internet-era rap production with playful synths, light drum bounce, and simple catchy motifs. + +## Rhythm & Drums + +Light trap drums, crisp claps, airy hats, bouncing percussion. + +## Bass & Low End + +Clean 808s, usually less distorted and more buoyant. + +## Harmony, Melody & Sound Palette + +Bell-like leads, digital plucks, bright synths, simple arpeggios. + +## Vocal / Rap Approach + +Relaxed, playful, melodic or conversational delivery. + +## Arrangement + +Short sections, repetitive hooks, minimal layering. + +## Mood & Energy + +Playful, airy, digital, effortless. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/028_pluggnb.md b/music_styles/028_pluggnb.md new file mode 100644 index 0000000..b170517 --- /dev/null +++ b/music_styles/028_pluggnb.md @@ -0,0 +1,36 @@ +# PluggnB + +**Family:** Trap / R&B +**Typical tempo:** 125–160 BPM + +## Core Identity + +Plugg-derived drums blended with lush R&B harmony, sparkling synths, and melodic vocal writing. + +## Rhythm & Drums + +Light trap percussion with soft attack and syncopated hats. + +## Bass & Low End + +Smooth 808 or sub that follows chord roots. + +## Harmony, Melody & Sound Palette + +Rich seventh/ninth chords, glossy keys, bright leads, pads. + +## Vocal / Rap Approach + +Melodic rap, stacked harmonies, soft falsetto or intimate delivery. + +## Arrangement + +Hook-heavy, fluid sections, layered vocal moments. + +## Mood & Energy + +Romantic, glossy, dreamy, emotional. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/029_rage.md b/music_styles/029_rage.md new file mode 100644 index 0000000..d507a48 --- /dev/null +++ b/music_styles/029_rage.md @@ -0,0 +1,36 @@ +# Rage + +**Family:** Trap / Electronic +**Typical tempo:** 130–165 BPM + +## Core Identity + +Hyper-energetic rap built on distorted synth leads, huge 808s, bright digital textures, and repetitive festival-like momentum. + +## Rhythm & Drums + +Fast hats, hard claps, aggressive kicks, sparse but forceful patterns. + +## Bass & Low End + +Large clipped or distorted 808s with simple movement. + +## Harmony, Melody & Sound Palette + +Saw leads, arpeggios, video-game-like synths, supersaws, bright distortion. + +## Vocal / Rap Approach + +Repetitive, shouted, melodic or chant-based delivery. + +## Arrangement + +Short build, explosive drop, repeated hook, minimal breakdown. + +## Mood & Energy + +Chaotic, euphoric, aggressive, futuristic. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/030_drill.md b/music_styles/030_drill.md new file mode 100644 index 0000000..74d24c1 --- /dev/null +++ b/music_styles/030_drill.md @@ -0,0 +1,36 @@ +# Drill + +**Family:** Drill +**Typical tempo:** 135–150 BPM + +## Core Identity + +Dark street rap defined by sliding bass, syncopated kick patterns, sparse minor-key melodies, and tense vocal cadence. + +## Rhythm & Drums + +Off-grid-feeling kicks, sharp snares, rapid hats, percussive syncopation. + +## Bass & Low End + +Gliding 808s with pitch bends and long slides. + +## Harmony, Melody & Sound Palette + +Dark piano, bells, strings, choirs, sparse ambience. + +## Vocal / Rap Approach + +Clipped, rhythmically precise, confrontational delivery. + +## Arrangement + +Short intros, verse-heavy structure, hooks with strong rhythmic repetition. + +## Mood & Energy + +Tense, cold, menacing, urgent. + +## Performance Detail + +The kick and 808 should interlock rather than constantly hit together; bass slides need deliberate pitch targets. diff --git a/music_styles/031_chicago_drill.md b/music_styles/031_chicago_drill.md new file mode 100644 index 0000000..3aea027 --- /dev/null +++ b/music_styles/031_chicago_drill.md @@ -0,0 +1,36 @@ +# Chicago Drill + +**Family:** Drill / Regional +**Typical tempo:** 130–150 BPM + +## Core Identity + +Early drill aesthetic with raw minimalism, stark street energy, repetitive melodic loops, and blunt rhythmic force. + +## Rhythm & Drums + +Simple hard drums, rolling hats, direct clap/snare patterns. + +## Bass & Low End + +Heavy 808s, less ornate than later UK-style sliding bass. + +## Harmony, Melody & Sound Palette + +Dark synths, bells, simple minor motifs. + +## Vocal / Rap Approach + +Direct, repetitive, forceful, often less technically busy. + +## Arrangement + +Long verses, repeated hooks, deliberately minimal development. + +## Mood & Energy + +Raw, stark, aggressive, bleak. + +## Performance Detail + +The kick and 808 should interlock rather than constantly hit together; bass slides need deliberate pitch targets. diff --git a/music_styles/032_uk_drill.md b/music_styles/032_uk_drill.md new file mode 100644 index 0000000..abdfd6c --- /dev/null +++ b/music_styles/032_uk_drill.md @@ -0,0 +1,36 @@ +# UK Drill + +**Family:** Drill / Regional +**Typical tempo:** 138–145 BPM + +## Core Identity + +Polished, rhythmically intricate drill with sliding bass, syncopated kicks, eerie melodies, and sharply articulated flows. + +## Rhythm & Drums + +Complex kick placement, tight snare, fast hat patterns, percussion accents. + +## Bass & Low End + +Highly mobile sliding 808s with deliberate pitch choreography. + +## Harmony, Melody & Sound Palette + +Dark piano, bells, strings, choir, sparse atmospheric samples. + +## Vocal / Rap Approach + +Precise, clipped, percussive cadence with frequent rhythmic switches. + +## Arrangement + +Tension intro, verse-led arrangement, hook sections with strong bass movement. + +## Mood & Energy + +Cold, technical, threatening, cinematic. + +## Performance Detail + +The kick and 808 should interlock rather than constantly hit together; bass slides need deliberate pitch targets. diff --git a/music_styles/033_brooklyn_drill.md b/music_styles/033_brooklyn_drill.md new file mode 100644 index 0000000..66ff183 --- /dev/null +++ b/music_styles/033_brooklyn_drill.md @@ -0,0 +1,36 @@ +# Brooklyn Drill + +**Family:** Drill / Regional +**Typical tempo:** 138–150 BPM + +## Core Identity + +New York drill blending UK-influenced production with more forceful American vocal phrasing and energetic hooks. + +## Rhythm & Drums + +UK-drill-style kicks and hats with harder punch. + +## Bass & Low End + +Sliding 808s, often louder and more aggressive. + +## Harmony, Melody & Sound Palette + +Dark pianos, brass, strings, vocal chops, ominous synths. + +## Vocal / Rap Approach + +Commanding, energetic, punchline-heavy delivery. + +## Arrangement + +Hook-driven, compact sections, frequent drops and vocal callouts. + +## Mood & Energy + +Aggressive, energetic, urban, imposing. + +## Performance Detail + +The kick and 808 should interlock rather than constantly hit together; bass slides need deliberate pitch targets. diff --git a/music_styles/034_jersey_club_rap.md b/music_styles/034_jersey_club_rap.md new file mode 100644 index 0000000..1eff8c0 --- /dev/null +++ b/music_styles/034_jersey_club_rap.md @@ -0,0 +1,36 @@ +# Jersey Club Rap + +**Family:** Club / Rap +**Typical tempo:** 135–155 BPM + +## Core Identity + +Rap over fast Jersey club rhythms, characterized by chopped kick patterns, repeated vocal edits, and dance-floor momentum. + +## Rhythm & Drums + +Rapid triplet/bounce kicks, claps, chopped percussion, rhythmic stop-starts. + +## Bass & Low End + +Short sub hits or bass pulses; rhythm takes priority over sustain. + +## Harmony, Melody & Sound Palette + +Vocal chops, simple synth hooks, club samples. + +## Vocal / Rap Approach + +Short, catchy, rhythmic phrases; delivery often mirrors kick pattern. + +## Arrangement + +Compact sections, quick transitions, repeated dance breaks. + +## Mood & Energy + +Kinetic, playful, club-focused, high-energy. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/035_phonk.md b/music_styles/035_phonk.md new file mode 100644 index 0000000..747eea1 --- /dev/null +++ b/music_styles/035_phonk.md @@ -0,0 +1,32 @@ +# Phonk + +**Family:** Memphis-Derived / Electronic +**Typical tempo:** 80–130 BPM + +## Core Identity + +Modernized Memphis-inspired hip-hop using lo-fi vocal samples, cowbells, distorted bass, and dark retro texture. + +## Rhythm & Drums + +Dry drums, cowbell rhythm, crunchy snares, trap-influenced hats. + +## Bass & Low End + +Distorted sub/808 with saturated mids. + +## Harmony, Melody & Sound Palette + +Cowbells, Memphis vocal cuts, horror textures, vinyl/tape effects. + +## Vocal / Rap Approach + +Often sample-led; if original vocals are used, keep them sparse and gritty. + +## Arrangement + +Loop-driven, short sections, heavy repetition. + +## Mood & Energy + +Dark, retro, hypnotic, gritty. diff --git a/music_styles/036_drift_phonk.md b/music_styles/036_drift_phonk.md new file mode 100644 index 0000000..b9b56af --- /dev/null +++ b/music_styles/036_drift_phonk.md @@ -0,0 +1,32 @@ +# Drift Phonk + +**Family:** Electronic / Aggressive +**Typical tempo:** 120–170 BPM + +## Core Identity + +High-energy phonk derivative built for driving momentum, distorted low end, repetitive cowbell leads, and hard compression. + +## Rhythm & Drums + +Fast hard kicks, sharp snares, driving hats. + +## Bass & Low End + +Heavily distorted bass/808, often clipped for aggression. + +## Harmony, Melody & Sound Palette + +Prominent cowbell melody, dark synth layers, impact FX. + +## Vocal / Rap Approach + +Vocals are usually chopped or secondary to the instrumental. + +## Arrangement + +Build/drop structure, strong repeated lead motif. + +## Mood & Energy + +Aggressive, mechanical, adrenaline-heavy. diff --git a/music_styles/037_horrorcore.md b/music_styles/037_horrorcore.md new file mode 100644 index 0000000..49a3044 --- /dev/null +++ b/music_styles/037_horrorcore.md @@ -0,0 +1,32 @@ +# Horrorcore + +**Family:** Dark / Theatrical +**Typical tempo:** 65–100 BPM + +## Core Identity + +Hip-hop framed with horror imagery, ominous cinematic sound design, unsettling harmony, and theatrical vocal character. + +## Rhythm & Drums + +Heavy, sparse, often boom-bap or trap-derived. + +## Bass & Low End + +Dark sub, low drones, sampled bass. + +## Harmony, Melody & Sound Palette + +Horror-score strings, detuned piano, choirs, bells, sound effects. + +## Vocal / Rap Approach + +Narrative, theatrical, whispered-to-aggressive dynamics. + +## Arrangement + +Cinematic intros, story verses, dramatic hooks, tension breaks. + +## Mood & Energy + +Macabre, theatrical, suspenseful, sinister. diff --git a/music_styles/038_industrial_hip_hop.md b/music_styles/038_industrial_hip_hop.md new file mode 100644 index 0000000..41d5ea4 --- /dev/null +++ b/music_styles/038_industrial_hip_hop.md @@ -0,0 +1,36 @@ +# Industrial Hip-Hop + +**Family:** Experimental / Heavy +**Typical tempo:** 70–130 BPM + +## Core Identity + +Abrasive hip-hop using distorted percussion, metallic textures, machine noise, and dense sound design. + +## Rhythm & Drums + +Clanging hits, distorted kicks, clipped snares, mechanical loops. + +## Bass & Low End + +Distorted bass, drones, sub pressure, noise-layered low end. + +## Harmony, Melody & Sound Palette + +Metallic samples, feedback, synth noise, machinery, harsh processing. + +## Vocal / Rap Approach + +Aggressive, detached, spoken, shouted, or heavily processed. + +## Arrangement + +Abrupt transitions, breakdowns, texture changes, unconventional song form. + +## Mood & Energy + +Harsh, dystopian, confrontational, mechanical. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/039_experimental_hip_hop.md b/music_styles/039_experimental_hip_hop.md new file mode 100644 index 0000000..1da1a11 --- /dev/null +++ b/music_styles/039_experimental_hip_hop.md @@ -0,0 +1,36 @@ +# Experimental Hip-Hop + +**Family:** Experimental +**Typical tempo:** Variable 60–160 BPM + +## Core Identity + +Hip-hop that intentionally breaks conventions in rhythm, timbre, structure, or vocal design while preserving a rap-centered identity. + +## Rhythm & Drums + +Unusual meters, polymetric feel, broken grooves, unconventional samples. + +## Bass & Low End + +May be sub-heavy, absent, distorted, or rhythmically fragmented. + +## Harmony, Melody & Sound Palette + +Any palette: synthesis, found sound, granular texture, live instruments, noise. + +## Vocal / Rap Approach + +Nonstandard flow, spoken passages, pitch processing, abrupt cadence shifts. + +## Arrangement + +Unpredictable sections, asymmetry, beat switches, silence as arrangement. + +## Mood & Energy + +Inventive, challenging, surprising, boundary-pushing. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/040_glitch_hop.md b/music_styles/040_glitch_hop.md new file mode 100644 index 0000000..fbff876 --- /dev/null +++ b/music_styles/040_glitch_hop.md @@ -0,0 +1,36 @@ +# Glitch Hop + +**Family:** Electronic / Experimental +**Typical tempo:** 85–115 BPM + +## Core Identity + +Hip-hop/electronic hybrid using digital stutters, chopped edits, syncopated bass, and highly processed rhythmic detail. + +## Rhythm & Drums + +Punchy electronic drums with micro-edits, fills, retriggers, syncopation. + +## Bass & Low End + +Elastic synth bass, wobble, or glitchy low-end movement. + +## Harmony, Melody & Sound Palette + +Digital clicks, resampling, stutter edits, chopped synths. + +## Vocal / Rap Approach + +Rhythmic rap or sampled vocals; vocals may be heavily edited. + +## Arrangement + +Drop-oriented but groove-centered, with frequent micro-variation. + +## Mood & Energy + +Futuristic, playful, technical, kinetic. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/041_electronic_hip_hop.md b/music_styles/041_electronic_hip_hop.md new file mode 100644 index 0000000..3479492 --- /dev/null +++ b/music_styles/041_electronic_hip_hop.md @@ -0,0 +1,32 @@ +# Electronic Hip-Hop + +**Family:** Electronic +**Typical tempo:** 75–150 BPM + +## Core Identity + +Hip-hop built primarily from synthesis, drum machines, and electronic sound design rather than sample-based production. + +## Rhythm & Drums + +Programmed drums, synthetic percussion, precise transients. + +## Bass & Low End + +Sub bass, synth bass, or 808 depending substyle. + +## Harmony, Melody & Sound Palette + +Synth leads, pads, arps, electronic effects, digital texture. + +## Vocal / Rap Approach + +Any rap approach; often clean and rhythmically tight. + +## Arrangement + +Song structure can borrow from hip-hop or electronic music. + +## Mood & Energy + +Modern, synthetic, polished, flexible. diff --git a/music_styles/042_psychedelic_hip_hop.md b/music_styles/042_psychedelic_hip_hop.md new file mode 100644 index 0000000..7b0fc57 --- /dev/null +++ b/music_styles/042_psychedelic_hip_hop.md @@ -0,0 +1,36 @@ +# Psychedelic Hip-Hop + +**Family:** Psychedelic / Experimental +**Typical tempo:** 65–110 BPM + +## Core Identity + +Hip-hop with altered, dreamlike sound design: warped samples, phase movement, unusual stereo space, surreal harmony, and evolving textures. + +## Rhythm & Drums + +Groove can be laid-back or broken; use filtered and shifting percussion. + +## Bass & Low End + +Warm bass or sub with modulation and occasional pitch movement. + +## Harmony, Melody & Sound Palette + +Reversed samples, phaser/flanger, tape warble, synth drones, exotic timbres. + +## Vocal / Rap Approach + +Elastic, hypnotic, melodic, abstract, or heavily layered vocals. + +## Arrangement + +Evolving loops, transitions that morph rather than simply cut. + +## Mood & Energy + +Surreal, immersive, colorful, disorienting. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/043_neo_psychedelic_rap.md b/music_styles/043_neo_psychedelic_rap.md new file mode 100644 index 0000000..7f0fd2e --- /dev/null +++ b/music_styles/043_neo_psychedelic_rap.md @@ -0,0 +1,36 @@ +# Neo-Psychedelic Rap + +**Family:** Psychedelic / Modern +**Typical tempo:** 110–155 BPM + +## Core Identity + +Modern psychedelic rap combining trap or alternative drums with lush synth worlds, modulation, reverbs, and cinematic movement. + +## Rhythm & Drums + +Trap-informed drums with spacious gaps and textural effects. + +## Bass & Low End + +Gliding 808 or warm sub integrated into atmospheric mix. + +## Harmony, Melody & Sound Palette + +Wide pads, detuned synths, reversed guitars, granular vocal textures. + +## Vocal / Rap Approach + +Melodic rap, layered harmonies, ad-libs, processed vocal space. + +## Arrangement + +Hook-centered but with evolving sonic transitions. + +## Mood & Energy + +Dreamlike, futuristic, emotionally charged. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/044_trip_hop.md b/music_styles/044_trip_hop.md new file mode 100644 index 0000000..06eb981 --- /dev/null +++ b/music_styles/044_trip_hop.md @@ -0,0 +1,32 @@ +# Trip-Hop + +**Family:** Downtempo / Atmospheric +**Typical tempo:** 60–95 BPM + +## Core Identity + +Slow, moody breakbeat music blending hip-hop rhythm with cinematic ambience, dub space, and dark melodic texture. + +## Rhythm & Drums + +Slow breakbeats, dusty snares, deep pocket, occasional live percussion. + +## Bass & Low End + +Warm sub, dub bass, or melodic low-end loop. + +## Harmony, Melody & Sound Palette + +Moody strings, Rhodes, guitar, vinyl texture, atmospheric samples. + +## Vocal / Rap Approach + +Low-key rap, spoken word, breathy singing, or instrumental focus. + +## Arrangement + +Long intros/outros, cinematic builds, restrained hooks. + +## Mood & Energy + +Smoky, nocturnal, cinematic, introspective. diff --git a/music_styles/045_downtempo_hip_hop.md b/music_styles/045_downtempo_hip_hop.md new file mode 100644 index 0000000..34fe9d2 --- /dev/null +++ b/music_styles/045_downtempo_hip_hop.md @@ -0,0 +1,32 @@ +# Downtempo Hip-Hop + +**Family:** Downtempo / Chill +**Typical tempo:** 60–85 BPM + +## Core Identity + +Slow, spacious hip-hop designed around relaxed grooves, warm texture, and understated melodic movement. + +## Rhythm & Drums + +Soft drums, delayed percussion, loose swing. + +## Bass & Low End + +Rounded bass, low dynamic aggression. + +## Harmony, Melody & Sound Palette + +Pads, keys, guitar, mellow samples, ambient layers. + +## Vocal / Rap Approach + +Relaxed rap or sparse vocal presence. + +## Arrangement + +Gradual development, long loops, smooth transitions. + +## Mood & Energy + +Calm, reflective, spacious, late-night. diff --git a/music_styles/046_instrumental_hip_hop.md b/music_styles/046_instrumental_hip_hop.md new file mode 100644 index 0000000..b5902ec --- /dev/null +++ b/music_styles/046_instrumental_hip_hop.md @@ -0,0 +1,32 @@ +# Instrumental Hip-Hop + +**Family:** Beat / Instrumental +**Typical tempo:** 65–105 BPM + +## Core Identity + +Hip-hop where the beat itself carries the narrative through sample development, groove, texture, and arrangement rather than vocals. + +## Rhythm & Drums + +Any hip-hop drum language; groove must remain compelling without an MC. + +## Bass & Low End + +Bass should provide melodic/rhythmic identity. + +## Harmony, Melody & Sound Palette + +Samples, live instruments, synths, chops, turntablism, textures. + +## Vocal / Rap Approach + +No lead vocal required; vocal chops can function as instruments. + +## Arrangement + +More frequent variation, beat changes, breakdowns, and instrumental motifs. + +## Mood & Energy + +Depends on substyle; prioritize musical storytelling. diff --git a/music_styles/047_sampledelic_hip_hop.md b/music_styles/047_sampledelic_hip_hop.md new file mode 100644 index 0000000..0395863 --- /dev/null +++ b/music_styles/047_sampledelic_hip_hop.md @@ -0,0 +1,36 @@ +# Sampledelic Hip-Hop + +**Family:** Sample-Based / Experimental +**Typical tempo:** 75–110 BPM + +## Core Identity + +Dense collage-style hip-hop built from many manipulated samples, layered references, unusual juxtapositions, and evolving edits. + +## Rhythm & Drums + +Breakbeats layered with chopped percussion and found rhythms. + +## Bass & Low End + +Sample-derived bass or resampled low-end fragments. + +## Harmony, Melody & Sound Palette + +Multiple micro-samples, vocal snippets, records, film fragments, resampling. + +## Vocal / Rap Approach + +Rap can be sparse or rhythmically integrated into the collage. + +## Arrangement + +Constant detail changes while preserving a central groove. + +## Mood & Energy + +Playful, surreal, dense, crate-digger-oriented. + +## Performance Detail + +Maintain one recognizable anchor—groove, motif, bass figure, or vocal rhythm—while other elements mutate around it. diff --git a/music_styles/048_soul_hip_hop.md b/music_styles/048_soul_hip_hop.md new file mode 100644 index 0000000..f5ce660 --- /dev/null +++ b/music_styles/048_soul_hip_hop.md @@ -0,0 +1,32 @@ +# Soul Hip-Hop + +**Family:** Soul / Sample-Based +**Typical tempo:** 72–96 BPM + +## Core Identity + +Warm hip-hop drawing from soul records, gospel harmony, expressive vocals, and emotionally rich chord movement. + +## Rhythm & Drums + +Classic boom-bap or relaxed modern drums. + +## Bass & Low End + +Warm sampled/electric bass; melodic root movement. + +## Harmony, Melody & Sound Palette + +Soul vocals, Rhodes, strings, guitar, organ, warm chord progressions. + +## Vocal / Rap Approach + +Expressive, personal, reflective, confident; melodic hooks welcome. + +## Arrangement + +Verses supported by rich sample loops; hooks can open up harmonically. + +## Mood & Energy + +Warm, heartfelt, nostalgic, uplifting or bittersweet. diff --git a/music_styles/049_chipmunk_soul.md b/music_styles/049_chipmunk_soul.md new file mode 100644 index 0000000..efa603c --- /dev/null +++ b/music_styles/049_chipmunk_soul.md @@ -0,0 +1,32 @@ +# Chipmunk Soul + +**Family:** Soul / Sample-Based +**Typical tempo:** 80–100 BPM + +## Core Identity + +Soul-sampling style built around noticeably pitch-raised vocal samples, energetic chops, and bright emotional contrast against hard drums. + +## Rhythm & Drums + +Punchy boom-bap or early-2000s-style drums. + +## Bass & Low End + +Simple bass supporting sample roots. + +## Harmony, Melody & Sound Palette + +High-pitched soul vocal phrases, chopped hooks, strings, piano, gospel fragments. + +## Vocal / Rap Approach + +Confident rap with room for sample call-and-response. + +## Arrangement + +Strong sampled hook, verses with reduced sample density, dramatic chops. + +## Mood & Energy + +Triumphant, nostalgic, emotional, energetic. diff --git a/music_styles/050_gospel_rap.md b/music_styles/050_gospel_rap.md new file mode 100644 index 0000000..e10bda1 --- /dev/null +++ b/music_styles/050_gospel_rap.md @@ -0,0 +1,32 @@ +# Gospel Rap + +**Family:** Soul / Spiritual +**Typical tempo:** 70–105 BPM + +## Core Identity + +Hip-hop that uses gospel musical language—choirs, organ, uplifting harmony, communal dynamics—within a rap song framework. + +## Rhythm & Drums + +Can be boom-bap, trap, live drums, or handclap-driven. + +## Bass & Low End + +Warm bass, organ-supported low end, or 808 depending modernity. + +## Harmony, Melody & Sound Palette + +Choir, Hammond organ, piano, handclaps, strings, major/extended harmony. + +## Vocal / Rap Approach + +Earnest, declarative, inspirational; sung choir hooks fit strongly. + +## Arrangement + +Builds toward larger choruses, call-and-response, dynamic lifts. + +## Mood & Energy + +Uplifting, reverent, triumphant, communal. diff --git a/music_styles/051_funk_rap.md b/music_styles/051_funk_rap.md new file mode 100644 index 0000000..324b2c8 --- /dev/null +++ b/music_styles/051_funk_rap.md @@ -0,0 +1,32 @@ +# Funk Rap + +**Family:** Funk / Groove +**Typical tempo:** 85–110 BPM + +## Core Identity + +Hip-hop centered on syncopated basslines, funk guitar, punchy drums, and danceable rhythmic interplay. + +## Rhythm & Drums + +Tight kick/snare groove, ghost notes, claps, percussion. + +## Bass & Low End + +Highly active electric or synth bassline. + +## Harmony, Melody & Sound Palette + +Wah guitar, clavinet, brass, synth stabs, talkbox-style textures. + +## Vocal / Rap Approach + +Rhythmic, charismatic, playful or boastful delivery. + +## Arrangement + +Groove-driven sections, breakdowns, instrumental fills. + +## Mood & Energy + +Bouncy, confident, playful, physical. diff --git a/music_styles/052_disco_rap.md b/music_styles/052_disco_rap.md new file mode 100644 index 0000000..4b64f45 --- /dev/null +++ b/music_styles/052_disco_rap.md @@ -0,0 +1,36 @@ +# Disco Rap + +**Family:** Funk / Dance +**Typical tempo:** 100–125 BPM + +## Core Identity + +Hip-hop blended with disco grooves, four-on-the-floor influence, bright strings, rhythm guitar, and dancefloor bass. + +## Rhythm & Drums + +Four-on-the-floor or disco-inflected kick with claps and open hats. + +## Bass & Low End + +Moving octave bassline or disco-funk bass. + +## Harmony, Melody & Sound Palette + +Strings, piano, rhythm guitar, bright synths, handclaps. + +## Vocal / Rap Approach + +Party-oriented rhythmic rap, chant hooks, crowd interaction. + +## Arrangement + +Verse/hook with dance breaks and extended groove sections. + +## Mood & Energy + +Celebratory, bright, glamorous, danceable. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/053_randb_rap.md b/music_styles/053_randb_rap.md new file mode 100644 index 0000000..eaac8bc --- /dev/null +++ b/music_styles/053_randb_rap.md @@ -0,0 +1,32 @@ +# R&B Rap + +**Family:** R&B / Melodic +**Typical tempo:** 70–100 BPM or 130–160 half-time + +## Core Identity + +Hip-hop blended with smooth contemporary R&B harmony, polished drums, melodic hooks, and intimate vocal production. + +## Rhythm & Drums + +Soft punchy drums, trap/R&B hats, clean snaps. + +## Bass & Low End + +Smooth sub or 808 kept controlled. + +## Harmony, Melody & Sound Palette + +Electric piano, pads, guitar, lush chords, vocal textures. + +## Vocal / Rap Approach + +Rap verses with sung hooks, melodic phrasing, close-mic intimacy. + +## Arrangement + +Strong verse/pre-hook/hook structure, bridges common. + +## Mood & Energy + +Smooth, romantic, polished, emotional. diff --git a/music_styles/054_neo_soul_hip_hop.md b/music_styles/054_neo_soul_hip_hop.md new file mode 100644 index 0000000..e3e7db9 --- /dev/null +++ b/music_styles/054_neo_soul_hip_hop.md @@ -0,0 +1,32 @@ +# Neo-Soul Hip-Hop + +**Family:** Soul / Jazz +**Typical tempo:** 68–95 BPM + +## Core Identity + +Hip-hop with neo-soul harmony, live-feeling instrumentation, deep pocket, and sophisticated chord voicings. + +## Rhythm & Drums + +Loose pocket, ghost notes, rimshots, brushed textures. + +## Bass & Low End + +Warm electric/upright bass with melodic movement. + +## Harmony, Melody & Sound Palette + +Rhodes, guitar, organ, jazz extensions, live keys, subtle strings. + +## Vocal / Rap Approach + +Conversational rap, soulful singing, understated dynamics. + +## Arrangement + +Organic evolution, instrumental bridges, layered harmonies. + +## Mood & Energy + +Warm, intimate, sophisticated, reflective. diff --git a/music_styles/055_pop_rap.md b/music_styles/055_pop_rap.md new file mode 100644 index 0000000..bc2b2db --- /dev/null +++ b/music_styles/055_pop_rap.md @@ -0,0 +1,32 @@ +# Pop Rap + +**Family:** Commercial / Pop +**Typical tempo:** 85–115 BPM or 120–160 half-time + +## Core Identity + +Accessible hip-hop with concise songwriting, polished production, strong hooks, and broad melodic appeal. + +## Rhythm & Drums + +Clean, punchy, radio-ready drums. + +## Bass & Low End + +Controlled bass/808, clear translation on small speakers. + +## Harmony, Melody & Sound Palette + +Simple memorable chords, synths, guitar, bright motifs. + +## Vocal / Rap Approach + +Clear rap verses and highly memorable melodic hooks. + +## Arrangement + +Short intro, hook early, compact verses, bridge, final hook. + +## Mood & Energy + +Catchy, polished, energetic, emotionally direct. diff --git a/music_styles/056_party_rap.md b/music_styles/056_party_rap.md new file mode 100644 index 0000000..f2c7f29 --- /dev/null +++ b/music_styles/056_party_rap.md @@ -0,0 +1,36 @@ +# Party Rap + +**Family:** Club / Commercial +**Typical tempo:** 90–120 BPM + +## Core Identity + +Upbeat hip-hop designed for group energy, memorable slogans, simple rhythmic hooks, and immediate dancefloor response. + +## Rhythm & Drums + +Hard kicks, claps, bright percussion, danceable swing. + +## Bass & Low End + +Strong bass pulse without overcomplication. + +## Harmony, Melody & Sound Palette + +Bright synths, brass stabs, vocal chops, simple riffs. + +## Vocal / Rap Approach + +Chants, call-and-response, short memorable phrases. + +## Arrangement + +Frequent hooks, drops, breakdowns, crowd-response sections. + +## Mood & Energy + +Fun, social, energetic, uncomplicated. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/057_club_rap.md b/music_styles/057_club_rap.md new file mode 100644 index 0000000..bddc6ef --- /dev/null +++ b/music_styles/057_club_rap.md @@ -0,0 +1,36 @@ +# Club Rap + +**Family:** Club / Commercial +**Typical tempo:** 95–135 BPM + +## Core Identity + +Bass-forward rap optimized for loud playback, rhythmic impact, clear hooks, and repetitive movement. + +## Rhythm & Drums + +Large kicks, claps, syncopated percussion, clean transients. + +## Bass & Low End + +Sub-heavy, simple, powerful bass or 808. + +## Harmony, Melody & Sound Palette + +Minimal synth hooks, stabs, vocal chops, risers. + +## Vocal / Rap Approach + +Direct, rhythmic, hook-focused, chant-ready. + +## Arrangement + +Fast access to hook, drops, short verses, instrumental breaks. + +## Mood & Energy + +Physical, confident, high-impact, nightlife-focused. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/058_miami_bass.md b/music_styles/058_miami_bass.md new file mode 100644 index 0000000..1284356 --- /dev/null +++ b/music_styles/058_miami_bass.md @@ -0,0 +1,36 @@ +# Miami Bass + +**Family:** Bass / Regional +**Typical tempo:** 110–135 BPM + +## Core Identity + +Fast Southern dance rap built around booming sub-bass, drum-machine patterns, syncopated rhythms, and party energy. + +## Rhythm & Drums + +808 drum machine, rapid kicks, claps, cowbell/percussion accents. + +## Bass & Low End + +Very deep sustained or pulsing sub-bass. + +## Harmony, Melody & Sound Palette + +Sparse synth stabs, electro textures, vocal chants. + +## Vocal / Rap Approach + +Rhythmic, energetic, repetitive, party-focused. + +## Arrangement + +Loop-driven with breakdowns designed for dancers. + +## Mood & Energy + +Loud, playful, bass-dominant, energetic. + +## Performance Detail + +Prioritize physical rhythm and fast recognition. Hooks should arrive quickly and low-end transients should remain uncluttered. diff --git a/music_styles/059_electro_hip_hop.md b/music_styles/059_electro_hip_hop.md new file mode 100644 index 0000000..efabe83 --- /dev/null +++ b/music_styles/059_electro_hip_hop.md @@ -0,0 +1,32 @@ +# Electro Hip-Hop + +**Family:** Electronic / Old School +**Typical tempo:** 105–130 BPM + +## Core Identity + +Early electronic hip-hop language featuring drum machines, robotic synths, vocoder textures, and breakdance-oriented grooves. + +## Rhythm & Drums + +TR-style electronic drums, syncopated kicks, handclaps. + +## Bass & Low End + +Synth bass, sequenced low-end patterns. + +## Harmony, Melody & Sound Palette + +Arpeggiators, vocoder, futuristic leads, electro bleeps. + +## Vocal / Rap Approach + +Rhythmic MCing, robotic processed phrases, call-and-response. + +## Arrangement + +Extended groove sections and instrumental breaks. + +## Mood & Energy + +Futuristic-retro, playful, mechanical, dance-oriented. diff --git a/music_styles/060_old_school_hip_hop.md b/music_styles/060_old_school_hip_hop.md new file mode 100644 index 0000000..d52bba0 --- /dev/null +++ b/music_styles/060_old_school_hip_hop.md @@ -0,0 +1,32 @@ +# Old-School Hip-Hop + +**Family:** Classic / Early +**Typical tempo:** 95–115 BPM + +## Core Identity + +Foundational late-1970s/early-1980s hip-hop with break-driven grooves, party MCing, simple rhyme patterns, and DJ-centered structure. + +## Rhythm & Drums + +Funk/disco breaks, handclaps, simple drum-machine support. + +## Bass & Low End + +Funk/disco bassline, often continuous and danceable. + +## Harmony, Melody & Sound Palette + +Breaks, rhythm guitar, horns, disco/funk loops, DJ cuts. + +## Vocal / Rap Approach + +Call-and-response, rhythmic boasting, crowd interaction. + +## Arrangement + +Long groove-based sections with alternating MC passages. + +## Mood & Energy + +Joyful, communal, rhythmic, foundational. diff --git a/music_styles/061_breakbeat_hip_hop.md b/music_styles/061_breakbeat_hip_hop.md new file mode 100644 index 0000000..0964ef0 --- /dev/null +++ b/music_styles/061_breakbeat_hip_hop.md @@ -0,0 +1,32 @@ +# Breakbeat Hip-Hop + +**Family:** Classic / Breaks +**Typical tempo:** 85–115 BPM + +## Core Identity + +Hip-hop emphasizing chopped or looped drum breaks, syncopated funk percussion, and rhythmic sample manipulation. + +## Rhythm & Drums + +Breaks are the centerpiece; preserve ghost notes and human swing. + +## Bass & Low End + +Bass should lock tightly to break accents. + +## Harmony, Melody & Sound Palette + +Funk/soul samples, percussion loops, short stabs. + +## Vocal / Rap Approach + +Rhythmic rap that rides changing drum accents. + +## Arrangement + +Break variations, fills, cuts, drum-only sections. + +## Mood & Energy + +Groovy, kinetic, sample-driven. diff --git a/music_styles/062_freestyle_rap.md b/music_styles/062_freestyle_rap.md new file mode 100644 index 0000000..755daa9 --- /dev/null +++ b/music_styles/062_freestyle_rap.md @@ -0,0 +1,36 @@ +# Freestyle Rap + +**Family:** Performance / Lyrical +**Typical tempo:** 80–100 BPM + +## Core Identity + +Beat design optimized for spontaneous MCing: clear pocket, predictable phrase lengths, restrained arrangement, and strong loop continuity. + +## Rhythm & Drums + +Steady, legible groove without excessive fills. + +## Bass & Low End + +Simple bass pattern that does not compete with cadence. + +## Harmony, Melody & Sound Palette + +One or two strong motifs, minimal harmonic changes. + +## Vocal / Rap Approach + +Open vocal space; adaptable to many flows and rhyme densities. + +## Arrangement + +Long 8/16-bar cycles, subtle transitions, few disruptive drops. + +## Mood & Energy + +Focused, flexible, cypher-ready. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/063_battle_rap.md b/music_styles/063_battle_rap.md new file mode 100644 index 0000000..ff01054 --- /dev/null +++ b/music_styles/063_battle_rap.md @@ -0,0 +1,36 @@ +# Battle Rap + +**Family:** Performance / Lyrical +**Typical tempo:** 78–98 BPM + +## Core Identity + +Sparse, aggressive hip-hop designed to foreground punchlines, cadence changes, and verbal impact. + +## Rhythm & Drums + +Hard snare, simple kick pattern, minimal rhythmic clutter. + +## Bass & Low End + +Controlled low end; avoid bass masking the voice. + +## Harmony, Melody & Sound Palette + +Dark stabs, tense strings/piano, minimal loops. + +## Vocal / Rap Approach + +Highly articulate, confrontational, punchline-heavy, stop-start delivery. + +## Arrangement + +Long verses, strategic pauses, limited hook dependence. + +## Mood & Energy + +Competitive, tense, direct, forceful. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/064_cypher_hip_hop.md b/music_styles/064_cypher_hip_hop.md new file mode 100644 index 0000000..3c3aa79 --- /dev/null +++ b/music_styles/064_cypher_hip_hop.md @@ -0,0 +1,36 @@ +# Cypher Hip-Hop + +**Family:** Performance / Lyrical +**Typical tempo:** 80–96 BPM + +## Core Identity + +Loop-centered hip-hop designed for multiple MCs to trade verses while maintaining a stable groove and neutral vocal space. + +## Rhythm & Drums + +Consistent boom-bap or stripped groove; modest fills. + +## Bass & Low End + +Simple looped bass that stays out of the midrange. + +## Harmony, Melody & Sound Palette + +Sample loop, keys, horns, or restrained atmosphere. + +## Vocal / Rap Approach + +Multiple distinct flows; beat should support handoffs between rappers. + +## Arrangement + +Extended verse blocks, short reset transitions, optional refrain. + +## Mood & Energy + +Communal, focused, energetic, lyrical. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/065_storytelling_rap.md b/music_styles/065_storytelling_rap.md new file mode 100644 index 0000000..77ee6c7 --- /dev/null +++ b/music_styles/065_storytelling_rap.md @@ -0,0 +1,36 @@ +# Storytelling Rap + +**Family:** Lyrical / Narrative +**Typical tempo:** 70–98 BPM + +## Core Identity + +Narrative-first hip-hop where musical choices support scene changes, pacing, tension, character, and emotional resolution. + +## Rhythm & Drums + +Steady drums with dynamic changes tied to narrative moments. + +## Bass & Low End + +Bass follows emotional arc rather than dominating. + +## Harmony, Melody & Sound Palette + +Cinematic samples, piano, strings, atmosphere, location-like sound design. + +## Vocal / Rap Approach + +Clear diction, varied tone, character voices, controlled pacing. + +## Arrangement + +Verses behave like scenes; transitions may mark time/place changes. + +## Mood & Energy + +Cinematic, immersive, reflective, dramatic. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/066_lyrical_hip_hop.md b/music_styles/066_lyrical_hip_hop.md new file mode 100644 index 0000000..7bc1b21 --- /dev/null +++ b/music_styles/066_lyrical_hip_hop.md @@ -0,0 +1,36 @@ +# Lyrical Hip-Hop + +**Family:** Lyrical +**Typical tempo:** 75–100 BPM + +## Core Identity + +Rap-centered production deliberately leaves space for complex writing, rhyme schemes, and nuanced vocal rhythm. + +## Rhythm & Drums + +Clear pocket, moderate density, strong snare reference. + +## Bass & Low End + +Simple supportive bass. + +## Harmony, Melody & Sound Palette + +Restrained sample or melodic loop with limited frequency clutter. + +## Vocal / Rap Approach + +Dense bars, internal rhymes, multi-syllabic patterns, dynamic cadence. + +## Arrangement + +Verse-dominant, hooks simple enough not to distract. + +## Mood & Energy + +Focused, intelligent, expressive, performance-first. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/067_technical_rap.md b/music_styles/067_technical_rap.md new file mode 100644 index 0000000..a101da4 --- /dev/null +++ b/music_styles/067_technical_rap.md @@ -0,0 +1,36 @@ +# Technical Rap + +**Family:** Lyrical / Technical +**Typical tempo:** 75–105 BPM or double-time + +## Core Identity + +Production tailored to intricate rhyme density, cadence shifts, breath control, and rhythmic precision. + +## Rhythm & Drums + +Very clear subdivision; crisp hats and snare provide timing landmarks. + +## Bass & Low End + +Tight low end with short decay. + +## Harmony, Melody & Sound Palette + +Minimal motifs, dark keys, simple loops, occasional accent stabs. + +## Vocal / Rap Approach + +Rapid internal rhyme, multi-syllabic patterns, tempo switches, precise articulation. + +## Arrangement + +Long verses with purposeful beat drops for emphasis. + +## Mood & Energy + +Controlled, intense, intricate, athletic. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/068_fast_rap_chopper.md b/music_styles/068_fast_rap_chopper.md new file mode 100644 index 0000000..7222bcc --- /dev/null +++ b/music_styles/068_fast_rap_chopper.md @@ -0,0 +1,36 @@ +# Fast Rap / Chopper + +**Family:** Lyrical / Technical +**Typical tempo:** 85–110 BPM with double-time vocal feel + +## Core Identity + +High-speed rap format designed for double-time or extremely dense syllabic delivery while preserving intelligibility. + +## Rhythm & Drums + +Simple, crisp, highly legible drums; avoid clutter at fast subdivisions. + +## Bass & Low End + +Short controlled bass notes or 808s. + +## Harmony, Melody & Sound Palette + +Minimal harmonic material; rhythmic stabs can mark phrase boundaries. + +## Vocal / Rap Approach + +Very fast articulation, repeated rhythmic cells, breath-aware phrase design. + +## Arrangement + +Sections should include brief rests, drops, or half-time resets. + +## Mood & Energy + +Energetic, technical, urgent, precision-focused. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/069_syllable_dense_rap.md b/music_styles/069_syllable_dense_rap.md new file mode 100644 index 0000000..80a597d --- /dev/null +++ b/music_styles/069_syllable_dense_rap.md @@ -0,0 +1,36 @@ +# Syllable-Dense Rap + +**Family:** Lyrical / Technical +**Typical tempo:** 72–100 BPM + +## Core Identity + +Hip-hop optimized for unusually dense lyric writing, internal rhymes, consonant detail, and constantly changing cadence. + +## Rhythm & Drums + +Stable groove, modest fills, strong timing anchors. + +## Bass & Low End + +Low-end kept simple and uncluttered. + +## Harmony, Melody & Sound Palette + +Sparse samples/keys with holes in the midrange. + +## Vocal / Rap Approach + +Dense multisyllabic rhyme chains, internal patterns, controlled rhythmic variation. + +## Arrangement + +Long verses, short hooks, occasional drum dropouts for verbal emphasis. + +## Mood & Energy + +Cerebral, intense, intricate, focused. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/070_spoken_word_hip_hop.md b/music_styles/070_spoken_word_hip_hop.md new file mode 100644 index 0000000..376684e --- /dev/null +++ b/music_styles/070_spoken_word_hip_hop.md @@ -0,0 +1,36 @@ +# Spoken-Word Hip-Hop + +**Family:** Lyrical / Poetic +**Typical tempo:** 55–90 BPM + +## Core Identity + +Minimal hip-hop supporting poetry-like delivery, dynamic speech rhythm, and emotional language rather than conventional rap cadence. + +## Rhythm & Drums + +Sparse percussion, brushes, rimshots, soft kicks, or no drums in sections. + +## Bass & Low End + +Subtle bass or drone. + +## Harmony, Melody & Sound Palette + +Piano, strings, ambient textures, jazz harmony, field recordings. + +## Vocal / Rap Approach + +Natural speech cadence, pauses, dynamic emphasis, intimate tone. + +## Arrangement + +Free-form sections, gradual builds, instrumental breathing room. + +## Mood & Energy + +Intimate, reflective, literary, emotionally exposed. + +## Performance Detail + +Protect vocal intelligibility: avoid busy midrange layers during dense verses and use instrumental accents at phrase endings. diff --git a/music_styles/071_emo_rap.md b/music_styles/071_emo_rap.md new file mode 100644 index 0000000..fd2a494 --- /dev/null +++ b/music_styles/071_emo_rap.md @@ -0,0 +1,32 @@ +# Emo Rap + +**Family:** Melodic / Emotional +**Typical tempo:** 115–155 BPM or slow half-time + +## Core Identity + +Emotionally vulnerable rap combining trap/lo-fi production with melodic vocals, guitar or piano motifs, and confessional writing. + +## Rhythm & Drums + +Soft trap drums, restrained hats, emotional pauses. + +## Bass & Low End + +Warm 808, often following chord roots. + +## Harmony, Melody & Sound Palette + +Guitar loops, piano, pads, vocal texture, minor/relative-major harmony. + +## Vocal / Rap Approach + +Melodic rap, fragile singing, layered doubles, intimate delivery. + +## Arrangement + +Hook-heavy, compact verses, bridge or breakdown for emotional peak. + +## Mood & Energy + +Vulnerable, melancholic, intimate, cathartic. diff --git a/music_styles/072_sad_rap.md b/music_styles/072_sad_rap.md new file mode 100644 index 0000000..16be841 --- /dev/null +++ b/music_styles/072_sad_rap.md @@ -0,0 +1,32 @@ +# Sad Rap + +**Family:** Melodic / Emotional +**Typical tempo:** 60–90 BPM or 120–150 half-time + +## Core Identity + +Melancholic rap built around sparse harmony, slow pacing, introspection, and subdued production. + +## Rhythm & Drums + +Soft, simple, low-impact drums. + +## Bass & Low End + +Rounded sub or quiet 808. + +## Harmony, Melody & Sound Palette + +Piano, guitar, ambient pads, rain/room textures, minimal motifs. + +## Vocal / Rap Approach + +Low-energy, reflective, melodic or spoken delivery. + +## Arrangement + +Long verses, restrained hooks, gradual dynamic movement. + +## Mood & Energy + +Somber, introspective, lonely, bittersweet. diff --git a/music_styles/073_bedroom_rap.md b/music_styles/073_bedroom_rap.md new file mode 100644 index 0000000..6aed5e5 --- /dev/null +++ b/music_styles/073_bedroom_rap.md @@ -0,0 +1,36 @@ +# Bedroom Rap + +**Family:** Lo-Fi / Indie +**Typical tempo:** 65–100 BPM + +## Core Identity + +DIY, intimate hip-hop that embraces imperfect recording texture, simple arrangements, and personal songwriting. + +## Rhythm & Drums + +Loose programmed drums, room-like texture, low-fi transients. + +## Bass & Low End + +Simple bass or sub; not overly polished. + +## Harmony, Melody & Sound Palette + +Home-recorded guitar/keys, cheap synths, room noise, tape saturation. + +## Vocal / Rap Approach + +Close, conversational, understated, sometimes imperfect by design. + +## Arrangement + +Compact, songlike forms with handmade transitions. + +## Mood & Energy + +Personal, warm, awkward-in-a-good-way, intimate. + +## Performance Detail + +Use degradation selectively. The mix can sound worn without becoming muddy; preserve a readable kick, snare, and vocal range. diff --git a/music_styles/074_indie_hip_hop.md b/music_styles/074_indie_hip_hop.md new file mode 100644 index 0000000..1ff5689 --- /dev/null +++ b/music_styles/074_indie_hip_hop.md @@ -0,0 +1,32 @@ +# Indie Hip-Hop + +**Family:** Underground / Alternative +**Typical tempo:** 65–115 BPM + +## Core Identity + +Artist-driven hip-hop with idiosyncratic production, unconventional influences, and less concern for mainstream structure. + +## Rhythm & Drums + +Varies widely; should feel intentional and characterful. + +## Bass & Low End + +Bass chosen for song identity, not genre convention. + +## Harmony, Melody & Sound Palette + +Indie rock, jazz, electronics, folk, soul, or experimental elements. + +## Vocal / Rap Approach + +Distinctive personal voice; can mix rap and singing. + +## Arrangement + +Flexible structures, unexpected bridges, instrumental passages. + +## Mood & Energy + +Individualistic, creative, authentic, exploratory. diff --git a/music_styles/075_lo_fi_underground.md b/music_styles/075_lo_fi_underground.md new file mode 100644 index 0000000..213d011 --- /dev/null +++ b/music_styles/075_lo_fi_underground.md @@ -0,0 +1,36 @@ +# Lo-Fi Underground + +**Family:** Underground / Lo-Fi +**Typical tempo:** 70–92 BPM + +## Core Identity + +Raw underground rap with degraded sample texture, dusty drums, narrow bandwidth, and deliberately unpolished sonics. + +## Rhythm & Drums + +Crunchy, clipped, dusty, slightly loose. + +## Bass & Low End + +Sampled bass or muted sub. + +## Harmony, Melody & Sound Palette + +Obscure chops, tape hiss, vinyl crackle, filtered loops. + +## Vocal / Rap Approach + +Low-key, dense, conversational, often dry and close. + +## Arrangement + +Loop-heavy, subtle changes, short hooks or none. + +## Mood & Energy + +Gritty, intimate, obscure, late-night. + +## Performance Detail + +Use degradation selectively. The mix can sound worn without becoming muddy; preserve a readable kick, snare, and vocal range. diff --git a/music_styles/076_grimy_boom_bap.md b/music_styles/076_grimy_boom_bap.md new file mode 100644 index 0000000..6176896 --- /dev/null +++ b/music_styles/076_grimy_boom_bap.md @@ -0,0 +1,36 @@ +# Grimy Boom Bap + +**Family:** Boom Bap / Dark +**Typical tempo:** 78–94 BPM + +## Core Identity + +A dirtier, more abrasive boom-bap variant with rough sampling, hard drums, low-mid weight, and street-level atmosphere. + +## Rhythm & Drums + +Crushed kicks, snapping snares, gritty hats, hard swing. + +## Bass & Low End + +Dirty sampled bass or saturated low-end loop. + +## Harmony, Melody & Sound Palette + +Dark soul/jazz chops, detuned piano, brass, vinyl grit. + +## Vocal / Rap Approach + +Forceful, bar-heavy, dry vocal presence. + +## Arrangement + +Long verse loops, abrupt mutes, sample drops, DJ cuts. + +## Mood & Energy + +Dirty, hard, urban, uncompromising. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/077_dark_boom_bap.md b/music_styles/077_dark_boom_bap.md new file mode 100644 index 0000000..06534e5 --- /dev/null +++ b/music_styles/077_dark_boom_bap.md @@ -0,0 +1,36 @@ +# Dark Boom Bap + +**Family:** Boom Bap / Dark +**Typical tempo:** 76–94 BPM + +## Core Identity + +Boom-bap built around ominous samples, minor harmony, sparse melodic motion, and cinematic tension. + +## Rhythm & Drums + +Hard but controlled; snare-forward groove. + +## Bass & Low End + +Deep sampled bass or sub reinforcement. + +## Harmony, Melody & Sound Palette + +Minor piano, horror/suspense strings, low brass, eerie vocal chops. + +## Vocal / Rap Approach + +Measured, serious, technically precise rap. + +## Arrangement + +Loop-focused with tension variations and dramatic drops. + +## Mood & Energy + +Nocturnal, sinister, focused, cinematic. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/078_jazz_boom_bap.md b/music_styles/078_jazz_boom_bap.md new file mode 100644 index 0000000..4415d55 --- /dev/null +++ b/music_styles/078_jazz_boom_bap.md @@ -0,0 +1,36 @@ +# Jazz Boom Bap + +**Family:** Boom Bap / Jazz +**Typical tempo:** 78–96 BPM + +## Core Identity + +Classic boom-bap drums paired with jazz samples, extended harmony, horn fragments, and swinging musical phrasing. + +## Rhythm & Drums + +Dusty kick/snare, swing, occasional brushed percussion. + +## Bass & Low End + +Upright/electric bass loops, walking fragments. + +## Harmony, Melody & Sound Palette + +Sax, trumpet, piano, vibraphone, Rhodes, jazz guitar. + +## Vocal / Rap Approach + +Relaxed but articulate, pocket-aware lyrical flow. + +## Arrangement + +Sample loop evolves through horn/piano variations and cutaways. + +## Mood & Energy + +Cool, sophisticated, smoky, head-nod. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/079_soulful_boom_bap.md b/music_styles/079_soulful_boom_bap.md new file mode 100644 index 0000000..9485377 --- /dev/null +++ b/music_styles/079_soulful_boom_bap.md @@ -0,0 +1,36 @@ +# Soulful Boom Bap + +**Family:** Boom Bap / Soul +**Typical tempo:** 78–96 BPM + +## Core Identity + +Boom-bap with warm soul samples, expressive chord movement, vocal chops, and emotionally resonant grooves. + +## Rhythm & Drums + +Punchy but warm, modest swing. + +## Bass & Low End + +Warm bass sample or electric bass. + +## Harmony, Melody & Sound Palette + +Soul vocals, strings, Rhodes, guitar, organ. + +## Vocal / Rap Approach + +Reflective, confident, heartfelt delivery. + +## Arrangement + +Verses use chopped loop; hooks open up with fuller sample phrase. + +## Mood & Energy + +Warm, nostalgic, triumphant or bittersweet. + +## Performance Detail + +Keep the groove human: slight swing and imperfect sample timing are usually more convincing than rigid quantization. diff --git a/music_styles/080_cinematic_hip_hop.md b/music_styles/080_cinematic_hip_hop.md new file mode 100644 index 0000000..cc4c649 --- /dev/null +++ b/music_styles/080_cinematic_hip_hop.md @@ -0,0 +1,36 @@ +# Cinematic Hip-Hop + +**Family:** Cinematic +**Typical tempo:** 60–110 BPM + +## Core Identity + +Hip-hop arranged like a film score, using dynamic builds, orchestral or ambient layers, scene-setting textures, and dramatic pacing. + +## Rhythm & Drums + +Can move from minimal percussion to large impact drums. + +## Bass & Low End + +Sub/bass follows dramatic arc, sometimes absent in intros. + +## Harmony, Melody & Sound Palette + +Strings, brass, piano, sound design, drones, impacts, ambience. + +## Vocal / Rap Approach + +Narrative or emotionally dramatic delivery; space for spoken sections. + +## Arrangement + +Multi-stage builds, breakdowns, climaxes, transitions, motif reprises. + +## Mood & Energy + +Epic, dramatic, immersive, visual. + +## Performance Detail + +Use motifs and dynamic range. Avoid stacking every large sound at once; save the widest orchestration for structural peaks. diff --git a/music_styles/081_orchestral_hip_hop.md b/music_styles/081_orchestral_hip_hop.md new file mode 100644 index 0000000..51c8b3c --- /dev/null +++ b/music_styles/081_orchestral_hip_hop.md @@ -0,0 +1,36 @@ +# Orchestral Hip-Hop + +**Family:** Cinematic +**Typical tempo:** 70–105 BPM + +## Core Identity + +Hip-hop built around orchestral instrumentation and arrangement while retaining a strong rap pocket. + +## Rhythm & Drums + +Hip-hop drums layered with timpani, orchestral percussion, cymbal swells. + +## Bass & Low End + +Deep bass plus low strings/brass support. + +## Harmony, Melody & Sound Palette + +Strings, brass, woodwinds, choir, piano, orchestral ostinatos. + +## Vocal / Rap Approach + +Commanding, cinematic, lyrical or narrative delivery. + +## Arrangement + +Clear builds, thematic reprises, orchestral interludes. + +## Mood & Energy + +Grand, serious, dramatic, stately. + +## Performance Detail + +Use motifs and dynamic range. Avoid stacking every large sound at once; save the widest orchestration for structural peaks. diff --git a/music_styles/082_epic_hip_hop.md b/music_styles/082_epic_hip_hop.md new file mode 100644 index 0000000..4e99e9c --- /dev/null +++ b/music_styles/082_epic_hip_hop.md @@ -0,0 +1,36 @@ +# Epic Hip-Hop + +**Family:** Cinematic / Anthemic +**Typical tempo:** 70–110 BPM or 140–160 half-time + +## Core Identity + +Large-scale hip-hop emphasizing huge drums, dramatic harmonic movement, broad synth/orchestral layers, and climactic hooks. + +## Rhythm & Drums + +Massive kicks/snares, impact drums, percussion builds. + +## Bass & Low End + +Powerful sub/808, often reinforced with orchestral lows. + +## Harmony, Melody & Sound Palette + +Brass, strings, choir, synth stacks, risers, impacts. + +## Vocal / Rap Approach + +Commanding, motivational, anthem-ready delivery. + +## Arrangement + +Build/drop/climax structure with repeated peak hook. + +## Mood & Energy + +Triumphant, intense, monumental, motivational. + +## Performance Detail + +Use motifs and dynamic range. Avoid stacking every large sound at once; save the widest orchestration for structural peaks. diff --git a/music_styles/083_minimal_hip_hop.md b/music_styles/083_minimal_hip_hop.md new file mode 100644 index 0000000..8a3ded9 --- /dev/null +++ b/music_styles/083_minimal_hip_hop.md @@ -0,0 +1,32 @@ +# Minimal Hip-Hop + +**Family:** Minimal +**Typical tempo:** 65–105 BPM + +## Core Identity + +Hip-hop reduced to a few essential elements so rhythm, vocal character, and negative space carry the track. + +## Rhythm & Drums + +Sparse kick/snare/hat pattern; every hit matters. + +## Bass & Low End + +One simple bass or 808 figure. + +## Harmony, Melody & Sound Palette + +Single motif, texture, stab, or small chord loop. + +## Vocal / Rap Approach + +Vocal is foregrounded; pauses and rhythmic nuance become important. + +## Arrangement + +Few layers, strong muting, subtle section changes. + +## Mood & Energy + +Focused, cool, dry, modern. diff --git a/music_styles/084_bass_heavy_hip_hop.md b/music_styles/084_bass_heavy_hip_hop.md new file mode 100644 index 0000000..8131b73 --- /dev/null +++ b/music_styles/084_bass_heavy_hip_hop.md @@ -0,0 +1,32 @@ +# Bass-Heavy Hip-Hop + +**Family:** Bass / Modern +**Typical tempo:** 65–150 BPM + +## Core Identity + +Hip-hop designed around dominant low-frequency impact while retaining enough headroom and midrange space for drums and vocals. + +## Rhythm & Drums + +Hard, simple drums with clear transient separation. + +## Bass & Low End + +Primary feature: large sub, 808, synth bass, slides or sustained notes. + +## Harmony, Melody & Sound Palette + +Minimal mids; sparse motifs prevent masking. + +## Vocal / Rap Approach + +Direct, rhythmically strong delivery that can cut through dense low end. + +## Arrangement + +Drops and mutes emphasize bass arrival; hooks maximize low-end impact. + +## Mood & Energy + +Physical, powerful, dark or club-ready. diff --git a/music_styles/085_atmospheric_hip_hop.md b/music_styles/085_atmospheric_hip_hop.md new file mode 100644 index 0000000..84bf685 --- /dev/null +++ b/music_styles/085_atmospheric_hip_hop.md @@ -0,0 +1,32 @@ +# Atmospheric Hip-Hop + +**Family:** Atmospheric +**Typical tempo:** 60–100 BPM + +## Core Identity + +Spacious hip-hop where ambience, reverb, texture, and slow-moving harmony are as important as the drums. + +## Rhythm & Drums + +Soft or restrained drums; long tails and spacious placement. + +## Bass & Low End + +Warm sub, low drone, or minimal bass. + +## Harmony, Melody & Sound Palette + +Pads, reversed textures, field ambience, distant keys, vocal clouds. + +## Vocal / Rap Approach + +Intimate, melodic, reflective, or detached delivery. + +## Arrangement + +Long intros/outros, gradual layer changes, restrained transitions. + +## Mood & Energy + +Immersive, reflective, nocturnal, spacious. diff --git a/music_styles/086_dream_rap.md b/music_styles/086_dream_rap.md new file mode 100644 index 0000000..24c956f --- /dev/null +++ b/music_styles/086_dream_rap.md @@ -0,0 +1,32 @@ +# Dream Rap + +**Family:** Atmospheric / Dreamy +**Typical tempo:** 65–145 BPM + +## Core Identity + +Ethereal rap using soft percussion, shimmering harmony, blurred textures, and emotionally distant or surreal vocal presentation. + +## Rhythm & Drums + +Soft trap/lo-fi drums, airy hats, gentle transients. + +## Bass & Low End + +Smooth sub/808 with little distortion. + +## Harmony, Melody & Sound Palette + +Dream pads, chorus guitar, bells, reversed textures, reverb clouds. + +## Vocal / Rap Approach + +Breathy, melodic, detached, layered, occasionally whispered. + +## Arrangement + +Simple hooks, floating verse sections, long ambience tails. + +## Mood & Energy + +Dreamlike, wistful, weightless, surreal. diff --git a/music_styles/087_space_rap.md b/music_styles/087_space_rap.md new file mode 100644 index 0000000..b85dab4 --- /dev/null +++ b/music_styles/087_space_rap.md @@ -0,0 +1,32 @@ +# Space Rap + +**Family:** Futuristic / Atmospheric +**Typical tempo:** 70–150 BPM + +## Core Identity + +Futuristic hip-hop built around cosmic synth design, spacious stereo imaging, sci-fi ambience, and floating low end. + +## Rhythm & Drums + +Electronic drums with clean transients and wide spatial effects. + +## Bass & Low End + +Deep sub or gliding 808, sometimes modulated. + +## Harmony, Melody & Sound Palette + +Arps, sci-fi pads, FM tones, granular effects, orbital ambience. + +## Vocal / Rap Approach + +Cool, detached, melodic or technically precise rap. + +## Arrangement + +Expansive intros, drop-based verses, atmospheric bridges. + +## Mood & Energy + +Cosmic, futuristic, isolated, expansive. diff --git a/music_styles/088_futuristic_hip_hop.md b/music_styles/088_futuristic_hip_hop.md new file mode 100644 index 0000000..ed53d84 --- /dev/null +++ b/music_styles/088_futuristic_hip_hop.md @@ -0,0 +1,32 @@ +# Futuristic Hip-Hop + +**Family:** Futuristic +**Typical tempo:** 70–160 BPM + +## Core Identity + +Forward-looking hip-hop using novel synthesis, advanced sound design, unexpected rhythms, and polished digital production. + +## Rhythm & Drums + +Hybrid acoustic/electronic hits, unusual percussion, precise programming. + +## Bass & Low End + +Synthetic bass, resampled 808s, modulated sub. + +## Harmony, Melody & Sound Palette + +Granular synths, spectral textures, digital leads, unusual processing. + +## Vocal / Rap Approach + +Flexible: robotic, melodic, rapid, processed, or clean. + +## Arrangement + +Nonstandard transitions, evolving sound design, beat switches. + +## Mood & Energy + +Innovative, digital, sleek, unpredictable. diff --git a/music_styles/089_cyberpunk_hip_hop.md b/music_styles/089_cyberpunk_hip_hop.md new file mode 100644 index 0000000..aec9d1e --- /dev/null +++ b/music_styles/089_cyberpunk_hip_hop.md @@ -0,0 +1,32 @@ +# Cyberpunk Hip-Hop + +**Family:** Futuristic / Dark +**Typical tempo:** 75–150 BPM + +## Core Identity + +Dark futuristic rap combining industrial textures, neon synths, distorted bass, machine rhythms, and dystopian atmosphere. + +## Rhythm & Drums + +Mechanical drums, hard transients, glitch details. + +## Bass & Low End + +Distorted synth bass/808, sub drones. + +## Harmony, Melody & Sound Palette + +Dark synthwave leads, noise, alarms, granular effects, metallic ambience. + +## Vocal / Rap Approach + +Cold, processed, aggressive, spoken or melodic delivery. + +## Arrangement + +Cinematic intro, heavy drop, breakdowns with machine ambience. + +## Mood & Energy + +Dystopian, neon-lit, tense, technological. diff --git a/music_styles/090_retro_futuristic_hip_hop.md b/music_styles/090_retro_futuristic_hip_hop.md new file mode 100644 index 0000000..868ef17 --- /dev/null +++ b/music_styles/090_retro_futuristic_hip_hop.md @@ -0,0 +1,32 @@ +# Retro-Futuristic Hip-Hop + +**Family:** Futuristic / Retro +**Typical tempo:** 80–130 BPM + +## Core Identity + +Hip-hop imagining the future through vintage synth technology, analog textures, early digital sounds, and modern drum weight. + +## Rhythm & Drums + +Modern punch with retro drum-machine accents. + +## Bass & Low End + +Synth bass combining analog warmth with modern sub. + +## Harmony, Melody & Sound Palette + +Analog polysynths, FM keys, vintage arps, tape effects. + +## Vocal / Rap Approach + +Smooth, stylish, rhythmic delivery; melodic hooks fit well. + +## Arrangement + +Verse/hook with synth interludes and retro transitions. + +## Mood & Energy + +Nostalgic-futurist, stylish, cinematic, playful. diff --git a/music_styles/091_synthwave_hip_hop.md b/music_styles/091_synthwave_hip_hop.md new file mode 100644 index 0000000..482f25c --- /dev/null +++ b/music_styles/091_synthwave_hip_hop.md @@ -0,0 +1,32 @@ +# Synthwave Hip-Hop + +**Family:** Futuristic / Retro +**Typical tempo:** 85–120 BPM + +## Core Identity + +Hip-hop layered over 1980s-inspired synthwave harmony, gated drums, analog bass, arpeggios, and neon cinematic textures. + +## Rhythm & Drums + +Hip-hop groove blended with gated/snappy retro drums. + +## Bass & Low End + +Analog synth bass plus controlled sub. + +## Harmony, Melody & Sound Palette + +Juno-style pads, arps, bright leads, gated reverb, retro keys. + +## Vocal / Rap Approach + +Cool, melodic, cinematic, sometimes deadpan. + +## Arrangement + +Strong intro atmosphere, hook-driven sections, synth breakdown. + +## Mood & Energy + +Neon, nocturnal, nostalgic, cinematic. diff --git a/music_styles/092_latin_hip_hop.md b/music_styles/092_latin_hip_hop.md new file mode 100644 index 0000000..661aa30 --- /dev/null +++ b/music_styles/092_latin_hip_hop.md @@ -0,0 +1,32 @@ +# Latin Hip-Hop + +**Family:** Latin / Regional +**Typical tempo:** 80–110 BPM + +## Core Identity + +Hip-hop integrating Latin rhythmic language, percussion, melodic instruments, and regional musical references. + +## Rhythm & Drums + +Hip-hop drums blended with congas, timbales, claves, shakers, or dembow-adjacent accents. + +## Bass & Low End + +Warm bass or sub with syncopation. + +## Harmony, Melody & Sound Palette + +Guitar, brass, piano, regional percussion, sampled vocals. + +## Vocal / Rap Approach + +Rhythmic rap, bilingual phrasing where relevant, melodic hooks. + +## Arrangement + +Danceable verse/hook structure with percussion breaks. + +## Mood & Energy + +Rhythmic, warm, social, culturally textured. diff --git a/music_styles/093_reggae_hip_hop.md b/music_styles/093_reggae_hip_hop.md new file mode 100644 index 0000000..5f4eef7 --- /dev/null +++ b/music_styles/093_reggae_hip_hop.md @@ -0,0 +1,32 @@ +# Reggae Hip-Hop + +**Family:** Caribbean / Fusion +**Typical tempo:** 72–95 BPM + +## Core Identity + +Hip-hop fused with reggae’s offbeat rhythm, dub bass, spacious effects, and relaxed vocal pocket. + +## Rhythm & Drums + +Hip-hop drums with one-drop/steppers influence, rimshots, offbeat accents. + +## Bass & Low End + +Deep dub-style bassline is central. + +## Harmony, Melody & Sound Palette + +Skank guitar/keys, organ bubble, dub delay, horns. + +## Vocal / Rap Approach + +Relaxed rap, singjay-style melody, call-and-response. + +## Arrangement + +Verse/hook with dub breakdowns and delay throws. + +## Mood & Energy + +Laid-back, warm, conscious or celebratory. diff --git a/music_styles/094_dancehall_rap.md b/music_styles/094_dancehall_rap.md new file mode 100644 index 0000000..b4a29f2 --- /dev/null +++ b/music_styles/094_dancehall_rap.md @@ -0,0 +1,32 @@ +# Dancehall Rap + +**Family:** Caribbean / Fusion +**Typical tempo:** 90–110 BPM + +## Core Identity + +Rap over dancehall-influenced rhythms with syncopated drums, heavy bass, percussive vocal cadence, and energetic hooks. + +## Rhythm & Drums + +Dembow/dancehall-informed kick-snare patterns, percussion, shakers. + +## Bass & Low End + +Heavy but rhythmic bass, often short and punchy. + +## Harmony, Melody & Sound Palette + +Sparse synth stabs, plucks, vocal chops, tropical percussion. + +## Vocal / Rap Approach + +Highly rhythmic, melodic or chant-like delivery. + +## Arrangement + +Hook-heavy, dance-focused, quick transitions. + +## Mood & Energy + +Energetic, confident, warm, club-ready. diff --git a/music_styles/095_afro_hip_hop.md b/music_styles/095_afro_hip_hop.md new file mode 100644 index 0000000..667a262 --- /dev/null +++ b/music_styles/095_afro_hip_hop.md @@ -0,0 +1,32 @@ +# Afro Hip-Hop + +**Family:** African / Fusion +**Typical tempo:** 85–115 BPM + +## Core Identity + +Hip-hop blended with African rhythmic traditions, guitar/keyboard patterns, layered percussion, and regional groove concepts. + +## Rhythm & Drums + +Polyrhythmic percussion, shakers, claps, syncopated kick patterns. + +## Bass & Low End + +Warm melodic bass, sometimes less sub-heavy than trap. + +## Harmony, Melody & Sound Palette + +Guitars, marimba-like plucks, keys, horns, regional textures. + +## Vocal / Rap Approach + +Rhythmic rap, melodic refrains, call-and-response. + +## Arrangement + +Groove-led structure with instrumental movement. + +## Mood & Energy + +Warm, rhythmic, communal, vibrant. diff --git a/music_styles/096_afrobeats_rap.md b/music_styles/096_afrobeats_rap.md new file mode 100644 index 0000000..42aae02 --- /dev/null +++ b/music_styles/096_afrobeats_rap.md @@ -0,0 +1,32 @@ +# Afrobeats Rap + +**Family:** African / Fusion +**Typical tempo:** 95–115 BPM + +## Core Identity + +Rap integrated with Afrobeats production: syncopated percussion, melodic guitar/keys, smooth bass, and hook-led songwriting. + +## Rhythm & Drums + +Layered shakers, rimshots, kick syncopation, percussion loops. + +## Bass & Low End + +Warm rounded bass with melodic movement. + +## Harmony, Melody & Sound Palette + +Clean guitars, plucks, keys, bright pads, vocal textures. + +## Vocal / Rap Approach + +Melodic rap, sing-rap, smooth phrasing, catchy hooks. + +## Arrangement + +Short verses, recurring hook, danceable instrumental sections. + +## Mood & Energy + +Smooth, warm, infectious, uplifting. diff --git a/music_styles/097_grime.md b/music_styles/097_grime.md new file mode 100644 index 0000000..39f1fa9 --- /dev/null +++ b/music_styles/097_grime.md @@ -0,0 +1,32 @@ +# Grime + +**Family:** UK / Electronic +**Typical tempo:** 138–142 BPM + +## Core Identity + +Fast UK MC music built around sparse 140-BPM electronic production, aggressive square-wave bass, and sharply rhythmic delivery. + +## Rhythm & Drums + +Sparse punchy drums, syncopated snares, electronic percussion. + +## Bass & Low End + +Square-wave/sub bass, often simple and aggressive. + +## Harmony, Melody & Sound Palette + +Cold synths, eski-style bleeps, strings, metallic textures. + +## Vocal / Rap Approach + +Rapid, percussive, confrontational MC flow with strong cadence. + +## Arrangement + +8/16-bar loops, quick switches, minimal hook dependence. + +## Mood & Energy + +Cold, urgent, raw, competitive. diff --git a/music_styles/098_uk_hip_hop.md b/music_styles/098_uk_hip_hop.md new file mode 100644 index 0000000..603482b --- /dev/null +++ b/music_styles/098_uk_hip_hop.md @@ -0,0 +1,32 @@ +# UK Hip-Hop + +**Family:** UK / Regional +**Typical tempo:** 75–100 BPM + +## Core Identity + +British hip-hop outside grime/drill, often combining boom-bap, jazz, soul, spoken delivery, and distinctly UK vocal rhythm. + +## Rhythm & Drums + +Boom-bap or live-influenced drums; restrained swing. + +## Bass & Low End + +Warm bass or sample bass. + +## Harmony, Melody & Sound Palette + +Soul/jazz samples, piano, strings, understated modern textures. + +## Vocal / Rap Approach + +Clear UK cadence, storytelling, social observation, technical bars. + +## Arrangement + +Verse-forward with understated hooks and instrumental breathing room. + +## Mood & Energy + +Grounded, reflective, urban, lyrical. diff --git a/music_styles/099_french_hip_hop.md b/music_styles/099_french_hip_hop.md new file mode 100644 index 0000000..9a73cfd --- /dev/null +++ b/music_styles/099_french_hip_hop.md @@ -0,0 +1,32 @@ +# French Hip-Hop + +**Family:** Regional / European +**Typical tempo:** 75–155 BPM + +## Core Identity + +Broad French rap aesthetic spanning sample-heavy boom-bap, cinematic orchestration, dark street rap, and polished modern trap. + +## Rhythm & Drums + +Depends era: boom-bap, trap, or cinematic drums. + +## Bass & Low End + +Sample bass, sub, or 808 according to substyle. + +## Harmony, Melody & Sound Palette + +Piano, strings, chanson/soul samples, dark synths, orchestral elements. + +## Vocal / Rap Approach + +Highly rhythmic syllabic delivery; strong emphasis on phrasing and internal rhyme. + +## Arrangement + +Verse-led with memorable refrain; cinematic transitions common. + +## Mood & Energy + +Serious, lyrical, cinematic, streetwise. diff --git a/music_styles/100_japanese_hip_hop.md b/music_styles/100_japanese_hip_hop.md new file mode 100644 index 0000000..f49f8be --- /dev/null +++ b/music_styles/100_japanese_hip_hop.md @@ -0,0 +1,32 @@ +# Japanese Hip-Hop + +**Family:** Regional / Asian +**Typical tempo:** 70–155 BPM + +## Core Identity + +Broad Japanese hip-hop palette ranging from jazz-rich sample production to minimal modern trap and experimental electronic rap. + +## Rhythm & Drums + +Boom-bap, jazzy breaks, or clean trap drums depending direction. + +## Bass & Low End + +Warm sampled bass or modern 808. + +## Harmony, Melody & Sound Palette + +Jazz chords, city-pop fragments, keys, synths, atmospheric textures. + +## Vocal / Rap Approach + +Precise rhythmic phrasing; can be conversational, melodic, or technical. + +## Arrangement + +Clean, deliberate sections with strong production detail. + +## Mood & Energy + +Refined, rhythmic, atmospheric, stylistically flexible. diff --git a/music_styles/101_korean_hip_hop.md b/music_styles/101_korean_hip_hop.md new file mode 100644 index 0000000..2efd558 --- /dev/null +++ b/music_styles/101_korean_hip_hop.md @@ -0,0 +1,32 @@ +# Korean Hip-Hop + +**Family:** Regional / Asian +**Typical tempo:** 70–160 BPM + +## Core Identity + +Modern Korean hip-hop spanning boom-bap, trap, R&B hybrids, glossy electronic production, and technical rap performance. + +## Rhythm & Drums + +Clean, punchy modern drums; style-dependent. + +## Bass & Low End + +Controlled 808/sub, often polished and balanced. + +## Harmony, Melody & Sound Palette + +Trap synths, R&B chords, boom-bap samples, electronic textures. + +## Vocal / Rap Approach + +Technically precise rap, melodic hooks, rapid switches between rap and singing. + +## Arrangement + +Polished song structure with contrast sections and strong hooks. + +## Mood & Energy + +Polished, energetic, stylish, versatile. diff --git a/music_styles/102_latin_trap.md b/music_styles/102_latin_trap.md new file mode 100644 index 0000000..c8d386c --- /dev/null +++ b/music_styles/102_latin_trap.md @@ -0,0 +1,36 @@ +# Latin Trap + +**Family:** Latin / Trap +**Typical tempo:** 120–155 BPM + +## Core Identity + +Trap production with Latin melodic, rhythmic, and vocal sensibilities, combining 808 weight with regional harmonic and percussion colors. + +## Rhythm & Drums + +Trap hats/claps with Latin percussion accents. + +## Bass & Low End + +Sliding 808s and deep sub. + +## Harmony, Melody & Sound Palette + +Guitar, piano, plucks, atmospheric synths, Latin rhythmic motifs. + +## Vocal / Rap Approach + +Melodic rap, rhythmic phrasing, sung hooks. + +## Arrangement + +Hook-forward with sparse verses and rhythmic breakdowns. + +## Mood & Energy + +Dark-to-romantic, smooth, rhythmic, modern. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/music_styles/103_trap_soul.md b/music_styles/103_trap_soul.md new file mode 100644 index 0000000..f5337d2 --- /dev/null +++ b/music_styles/103_trap_soul.md @@ -0,0 +1,36 @@ +# Trap Soul + +**Family:** Trap / R&B +**Typical tempo:** 120–155 BPM half-time feel + +## Core Identity + +Emotional hybrid of trap drums and R&B songwriting, with lush harmony, intimate vocals, and restrained low-end power. + +## Rhythm & Drums + +Soft trap hats, snaps/claps, restrained kick patterns. + +## Bass & Low End + +Smooth 808/sub, usually warm rather than abrasive. + +## Harmony, Melody & Sound Palette + +Rhodes, guitar, pads, extended chords, ambient vocal textures. + +## Vocal / Rap Approach + +Sung-rap, layered harmonies, intimate lead, emotionally nuanced phrasing. + +## Arrangement + +Verse/pre-hook/hook, bridges, vocal breakdowns. + +## Mood & Energy + +Moody, sensual, introspective, polished. + +## Performance Detail + +Treat the 808 as both bass and rhythmic counterpoint; leave intentional gaps so slides and drum accents remain clear. diff --git a/server.cmd b/server.cmd index 20d35fa..2674842 100644 --- a/server.cmd +++ b/server.cmd @@ -1,6 +1,6 @@ @echo off -set PATH=%~dp0build\Release;%PATH% +set PATH=%~dp0.venv-vocal\Scripts;%~dp0build\Release;%PATH% rem Multi-GPU: set GGML_BACKEND to pick a device (CUDA0, CUDA1, Vulkan0...) rem set GGML_BACKEND=CUDA0 @@ -8,8 +8,8 @@ rem set GGML_BACKEND=Vulkan0 rem Q8_0 is near lossless. The quant is a straight swap: quantize.sh also rem builds Q6_K and Q5_K_M, and the native BF16 stays available. -yue-server.exe ^ - --host 0.0.0.0 ^ +build\Release-reference\yue-server.exe ^ + --host 127.0.0.1 ^ --port 8087 ^ --model models\YuE2-3B-Q8_0.gguf ^ --vae models\YuE2-Vae-F32.gguf ^ diff --git a/setup-vocal-separation.ps1 b/setup-vocal-separation.ps1 new file mode 100644 index 0000000..358c466 --- /dev/null +++ b/setup-vocal-separation.ps1 @@ -0,0 +1,28 @@ +$ErrorActionPreference = 'Stop' + +Write-Host 'Installing local vocal separation for YuE2...' +$python = Join-Path $PSScriptRoot '.venv-vocal\Scripts\python.exe' +if (-not (Test-Path -LiteralPath $python)) { + python -m venv (Join-Path $PSScriptRoot '.venv-vocal') + if ($LASTEXITCODE -ne 0) { + throw 'Could not create the vocal-separation environment. Confirm Python 3 is installed.' + } +} +& $python -m pip install 'audio-separator[gpu]==0.47.0' 'audioread>=3,<4' +if ($LASTEXITCODE -ne 0) { + throw 'Could not install audio-separator. Confirm Python and pip are available.' +} + +Write-Host '' +& $python -m pip install 'torch==2.11.0+cu128' 'torchvision==0.26.0+cu128' --index-url https://download.pytorch.org/whl/cu128 +if ($LASTEXITCODE -ne 0) { throw 'Could not install the CUDA PyTorch wheels.' } +$env:AUDIO_SEPARATOR_MODEL_DIR = Join-Path $env:TEMP 'yue2-audio-separator-models' +New-Item -ItemType Directory -Force -Path $env:AUDIO_SEPARATOR_MODEL_DIR | Out-Null +Write-Host 'Checking the audio-separator command and GPU provider...' +& (Join-Path $PSScriptRoot '.venv-vocal\Scripts\audio-separator.exe') --env_info +if ($LASTEXITCODE -ne 0) { + throw 'audio-separator did not start. See the output above for its CUDA or PATH issue.' +} + +Write-Host '' +Write-Host 'Setup complete. Restart YuE2, open a generated song menu, and choose Adjust vocal level.' diff --git a/src/audio-master.h b/src/audio-master.h new file mode 100644 index 0000000..d9f361a --- /dev/null +++ b/src/audio-master.h @@ -0,0 +1,129 @@ +#pragma once + +// Optional final-stage EBU R128 loudness normalization through FFmpeg. +// The input is kept in memory as float until mastering is requested. + +#include "audio-io.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +# include +# include +# include +extern char ** environ; +#endif + +static bool audio_master_ffmpeg(const float * audio, + int samples, + int sample_rate, + const std::string & profile, + std::vector * mastered, + std::string * error) { + if (!audio || samples <= 0 || !mastered) { + if (error) *error = "no audio to master"; + return false; + } + + const char * target = nullptr; + if (profile == "streaming") { + target = "-14"; + } else if (profile == "broadcast") { + target = "-23"; + } else { + if (error) *error = "unknown mastering profile"; + return false; + } + + namespace fs = std::filesystem; + static std::atomic serial{0}; + const uint64_t stamp = (uint64_t) std::chrono::steady_clock::now().time_since_epoch().count(); + const std::string stem = "yue2-master-" + std::to_string(stamp) + "-" + std::to_string(serial.fetch_add(1)); + + fs::path input_path; + fs::path output_path; + try { + const fs::path temp = fs::temp_directory_path(); + input_path = temp / (stem + "-in.wav"); + output_path = temp / (stem + "-out.wav"); + } catch (const std::exception & e) { + if (error) *error = std::string("cannot create temporary paths: ") + e.what(); + return false; + } + + struct Cleanup { + fs::path a, b; + ~Cleanup() { + std::error_code ec; + if (!a.empty()) fs::remove(a, ec); + if (!b.empty()) fs::remove(b, ec); + } + } cleanup{input_path, output_path}; + + const std::string input_wav = audio_encode_wav_f32(audio, samples, sample_rate); + if (input_wav.empty()) { + if (error) *error = "could not encode float audio for mastering"; + return false; + } + { + std::ofstream file(input_path, std::ios::binary); + file.write(input_wav.data(), (std::streamsize) input_wav.size()); + if (!file) { + if (error) *error = "could not write temporary audio for mastering"; + return false; + } + } + + const std::string filter = std::string("loudnorm=I=") + target + ":LRA=11:TP=-1:print_format=summary"; + std::string input = input_path.string(); + std::string output = output_path.string(); + std::string rate = std::to_string(sample_rate); + std::vector args = {"ffmpeg", "-hide_banner", "-nostdin", "-y", "-loglevel", "error", + "-i", input, "-af", filter, "-ar", rate, "-c:a", "pcm_f32le", output}; + std::vector argv; + argv.reserve(args.size() + 1); + for (std::string & arg : args) argv.push_back(arg.data()); + argv.push_back(nullptr); + + int exit_code = -1; +#ifdef _WIN32 + const intptr_t rc = _spawnvp(_P_WAIT, "ffmpeg", argv.data()); + if (rc != -1) exit_code = (int) rc; +#else + pid_t pid = -1; + if (posix_spawnp(&pid, "ffmpeg", nullptr, nullptr, argv.data(), environ) == 0) { + int status = 0; + if (waitpid(pid, &status, 0) >= 0 && WIFEXITED(status)) exit_code = WEXITSTATUS(status); + } +#endif + if (exit_code != 0) { + if (error) *error = "FFmpeg mastering failed; confirm ffmpeg is installed and supports the loudnorm filter"; + return false; + } + + int mastered_samples = 0; + int mastered_rate = 0; + float * decoded = audio_io_read_wav(output.c_str(), &mastered_samples, &mastered_rate); + if (!decoded) { + if (error) *error = "FFmpeg did not produce readable mastered audio"; + return false; + } + if (mastered_samples != samples || mastered_rate != sample_rate) { + free(decoded); + if (error) *error = "mastered audio format changed unexpectedly"; + return false; + } + mastered->assign(decoded, decoded + (size_t) mastered_samples * 2); + free(decoded); + return true; +} diff --git a/src/audio-video.h b/src/audio-video.h new file mode 100644 index 0000000..f6b314b --- /dev/null +++ b/src/audio-video.h @@ -0,0 +1,124 @@ +#pragma once + +// 16:9 video render for YouTube delivery: a still cover image plus the full +// length finished track becomes an MP4 (H.264 + AAC) via the local FFmpeg +// binary. Used by POST /render-video. The uploads are never modified. + +#include "audio-vocal-balance.h" // process runner, temp dir and error conventions + +#include +#include +#include + +// extension of an upload filename, lowercased, with a leading dot. Falls +// back when the client sends no filename. +static std::string video_ext_of(const std::string & filename, const char * fallback) { + const size_t dot = filename.find_last_of('.'); + std::string ext = dot == std::string::npos ? fallback : filename.substr(dot); + for (char & c : ext) c = (char) tolower((unsigned char) c); + return ext; +} + +static bool audio_render_video_ffmpeg(const std::string & cover_bytes, + const std::string & cover_ext, + const std::string & audio_bytes, + const std::string & audio_ext, + std::string * mp4, + std::string * error) { + if (cover_bytes.empty() || audio_bytes.empty() || !mp4) { + if (error) *error = "cover image and audio are both required"; + return false; + } + + // Bound the video timeline explicitly. At 1 fps, encoder lookahead can + // otherwise leave a long silent tail even with -shortest. + int samples=0,sample_rate=0; + float *decoded=audio_read_buf(reinterpret_cast(audio_bytes.data()),audio_bytes.size(),&samples,&sample_rate); + if(!decoded || samples<=0 || sample_rate<=0){free(decoded);if(error)*error="Audio could not be decoded for video export";return false;} + free(decoded); + const std::string duration=std::to_string(std::ceil((double)samples/sample_rate)); + namespace fs = std::filesystem; + static std::atomic serial{0}; + const uint64_t stamp = (uint64_t) std::chrono::steady_clock::now().time_since_epoch().count(); + const std::string stem = "yue2-video-" + std::to_string(stamp) + "-" + std::to_string(serial.fetch_add(1)); + fs::path dir; + try { + dir = fs::temp_directory_path() / stem; + fs::create_directories(dir); + } catch (const std::exception & e) { + if (error) *error = std::string("cannot create temporary paths: ") + e.what(); + return false; + } + struct Cleanup { + fs::path path; + ~Cleanup() { std::error_code ec; fs::remove_all(path, ec); } + } cleanup{dir}; + + const fs::path cover = dir / ("cover" + cover_ext); + const fs::path audio = dir / ("audio" + audio_ext); + const fs::path output = dir / "song.mp4"; + auto write = [&](const fs::path & path, const std::string & bytes, const char * what) { + std::ofstream file(path, std::ios::binary); + file.write(bytes.data(), (std::streamsize) bytes.size()); + if (!file && error) *error = std::string("could not write temporary ") + what; + return (bool) file; + }; + if (!write(cover, cover_bytes, "cover image") || !write(audio, audio_bytes, "audio")) { + return false; + } + + // Still image at 1 fps, cover-cropped to 1920x1080, broadcast-safe + // pixel format, faststart so YouTube can process while uploading. + std::vector render = {"ffmpeg", + "-hide_banner", + "-nostdin", + "-y", + "-loglevel", + "error", + "-loop", + "1", + "-framerate", + "1", + "-i", + cover.string(), + "-i", + audio.string(), + "-vf", + "scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,format=yuv420p", + "-c:v", + "libx264", + "-preset", + "medium", + "-crf", + "20", + "-c:a", + "aac", + "-b:a", + "192k", + "-t", + duration, + "-movflags", + "+faststart", + output.string()}; + const int status = audio_vocal_run("ffmpeg", render); + if (status != 0) { + if (error) { + *error = status == -1 ? "FFmpeg was not found. Install FFmpeg and add it to PATH, then restart YuE2." + : "FFmpeg could not render the video. Check that FFmpeg includes libx264."; + } + return false; + } + if (fs::file_size(output) > 256ULL * 1024 * 1024) { if (error) *error = "Video exceeds the 256 MiB delivery limit. Use a shorter track."; return false; } + std::ifstream file(output, std::ios::binary); + if (!file) { + if (error) *error = "FFmpeg did not produce a video file"; + return false; + } + mp4->assign(std::istreambuf_iterator(file), std::istreambuf_iterator()); + if (mp4->size() < 1024) { + if (error) *error = "FFmpeg produced an empty video file"; + mp4->clear(); + return false; + } + return true; +} diff --git a/src/audio-vocal-balance.h b/src/audio-vocal-balance.h new file mode 100644 index 0000000..e96576d --- /dev/null +++ b/src/audio-vocal-balance.h @@ -0,0 +1,278 @@ +#pragma once + +// Optional vocal balance correction using the local python-audio-separator +// command. The source mix is separated into vocal and accompaniment stems, +// the requested or estimated vocal gain is applied, then both stems are remixed. + +#include "audio-io.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# ifndef NOMINMAX +# define NOMINMAX +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +#else +# include +# include +# include +# include +# include +extern char ** environ; +#endif + +static std::string audio_tool_path(const std::string & name) { + if(name=="audio-separator"){ +#ifdef _WIN32 + const auto local=std::filesystem::absolute(".venv-vocal/Scripts/audio-separator.exe"); +#else + const auto local=std::filesystem::absolute(".venv-vocal/bin/audio-separator"); +#endif + if(std::filesystem::exists(local))return local.string(); + } + return name; +} +static bool audio_tool_available(const std::string & name) { + const auto resolved=audio_tool_path(name); + if(resolved!=name)return true; +#ifdef _WIN32 + char path[32768]; return SearchPathA(nullptr,name.c_str(),".exe",sizeof(path),path,nullptr)>0; +#else + const char * env=getenv("PATH");if(!env)return false;std::string paths(env);size_t start=0; + do {size_t end=paths.find(':',start);auto path=paths.substr(start,end-start)+"/"+name;if(access(path.c_str(),X_OK)==0)return true;if(end==std::string::npos)break;start=end+1;}while(true);return false; +#endif +} +static thread_local std::atomic * audio_process_cancel = nullptr; + +static int audio_vocal_run(const char * executable, std::vector & args) { + const auto resolved_executable=audio_tool_path(executable); + executable=resolved_executable.c_str(); + std::vector argv; + argv.reserve(args.size() + 1); + for (std::string & arg : args) argv.push_back(arg.data()); + argv.push_back(nullptr); +#ifdef _WIN32 + // Preserve embedded quotes and paths when _spawnvp joins argv on Windows. + std::vector quoted;quoted.reserve(args.size()); + for(const auto &arg:args){ + std::string q="\"";size_t slashes=0; + for(char c:arg){if(c=='\\'){slashes++;continue;} + if(c=='"'){q.append(slashes*2+1,'\\');q+='"';} + else{q.append(slashes,'\\');q+=c;}slashes=0; + } + q.append(slashes*2,'\\');q+='"';quoted.push_back(std::move(q)); + } + argv.clear();for(auto &arg:quoted)argv.push_back(arg.data());argv.push_back(nullptr); + const intptr_t rc = _spawnvp(_P_NOWAIT, executable, argv.data()); + if (rc == -1) return errno == ENOENT ? -1 : 1; + HANDLE process = (HANDLE)rc; + HANDLE group = CreateJobObjectW(nullptr, nullptr); + JOBOBJECT_EXTENDED_LIMIT_INFORMATION limits{}; + limits.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if (group) { SetInformationJobObject(group, JobObjectExtendedLimitInformation, &limits, sizeof(limits)); AssignProcessToJobObject(group, process); } + const auto deadline = std::chrono::steady_clock::now() + std::chrono::minutes(30); + while (WaitForSingleObject(process, 200) == WAIT_TIMEOUT) { + if ((audio_process_cancel && audio_process_cancel->load()) || std::chrono::steady_clock::now() >= deadline) { + if (group) TerminateJobObject(group, 1); + TerminateProcess(process, 1); WaitForSingleObject(process, 5000); + if (group) CloseHandle(group); CloseHandle(process); return 2; + } + } + DWORD status = 1; GetExitCodeProcess(process, &status); + if (group) CloseHandle(group); CloseHandle(process); + return (int)status; +#else + pid_t pid = -1; + posix_spawnattr_t attr; posix_spawnattr_init(&attr); + posix_spawnattr_setflags(&attr,POSIX_SPAWN_SETPGROUP); + posix_spawnattr_setpgroup(&attr,0); + const int spawn_error = posix_spawnp(&pid, executable, nullptr, &attr, argv.data(), environ); + posix_spawnattr_destroy(&attr); + if (spawn_error != 0) return spawn_error == ENOENT ? -1 : 1; + int status = 0; + const auto deadline = std::chrono::steady_clock::now() + std::chrono::minutes(30); + while (waitpid(pid, &status, WNOHANG) == 0) { + if ((audio_process_cancel && audio_process_cancel->load()) || std::chrono::steady_clock::now() >= deadline) { kill(-pid,SIGKILL); waitpid(pid,&status,0); return 2; } + usleep(200000); + } + if (!WIFEXITED(status)) return -1; + return WEXITSTATUS(status); +#endif +} + +static bool audio_vocal_balance_ffmpeg(const float * audio, + int samples, + int sample_rate, + float requested_gain_db, + bool auto_gain, + std::vector * balanced, + float * applied_gain_db, + std::string * error) { + if (!audio || samples <= 0 || !balanced || (!auto_gain && (!std::isfinite(requested_gain_db) || requested_gain_db < -12.0f || + requested_gain_db > 12.0f))) { + if (error) *error = "vocal gain must be between -12 and +12 dB"; + return false; + } + + namespace fs = std::filesystem; + static std::atomic serial{0}; + const uint64_t stamp = (uint64_t) std::chrono::steady_clock::now().time_since_epoch().count(); + const std::string stem = "yue2-vocal-" + std::to_string(stamp) + "-" + std::to_string(serial.fetch_add(1)); + fs::path dir; + try { + dir = fs::temp_directory_path() / stem; + fs::create_directories(dir); + } catch (const std::exception & e) { + if (error) *error = std::string("cannot create temporary paths: ") + e.what(); + return false; + } + struct Cleanup { + fs::path path; + ~Cleanup() { std::error_code ec; fs::remove_all(path, ec); } + } cleanup{dir}; + + const fs::path input = dir / "mix.wav"; + const fs::path output = dir / "balanced.wav"; + const std::string wav = audio_encode_wav_f32(audio, samples, sample_rate); + if (wav.empty()) { + if (error) *error = "could not encode audio for vocal balancing"; + return false; + } + { + std::ofstream file(input, std::ios::binary); + file.write(wav.data(), (std::streamsize) wav.size()); + if (!file) { + if (error) *error = "could not write temporary audio for vocal balancing"; + return false; + } + } + + const fs::path model_dir = dir / "stems"; + std::error_code ec; + fs::create_directories(model_dir, ec); + std::string input_arg = input.string(); + std::string out_arg = model_dir.string(); + std::string model_dir_arg = (fs::temp_directory_path() / "yue2-audio-separator-models").string(); + std::vector separate = {"audio-separator", input_arg, "--model_filename", + "model_bs_roformer_ep_317_sdr_12.9755.ckpt", "--output_format", "WAV", "--output_dir", out_arg, + "--model_file_dir", model_dir_arg, "--custom_output_names", + "{\"Vocals\":\"vocals\",\"Instrumental\":\"instrumental\"}", "--normalization", "1.0", + "--use_soundfile"}; + const int separation_status = audio_vocal_run("audio-separator", separate); + if (separation_status != 0) { + if (error) { + *error = separation_status == -1 + ? "audio-separator was not found. Run .\\setup-vocal-separation.ps1 from the YuE2 folder, then restart YuE2." + : "audio-separator failed. Check its CUDA provider with 'audio-separator --env_info'; the BS-RoFormer model downloads on first use, so check network access too."; + } + return false; + } + + const fs::path vocals = model_dir / "vocals.wav"; + const fs::path backing = model_dir / "instrumental.wav"; + if (!fs::exists(vocals) || !fs::exists(backing)) { + if (error) *error = "separator did not create the expected vocals and instrumental stems"; + return false; + } + float vocal_gain_db = requested_gain_db; + if (auto_gain) { + int vocal_samples = 0, vocal_rate = 0, backing_samples = 0, backing_rate = 0; + float * vocal = audio_io_read_wav(vocals.string().c_str(), &vocal_samples, &vocal_rate); + float * instrumental = audio_io_read_wav(backing.string().c_str(), &backing_samples, &backing_rate); + if (!vocal || !instrumental || vocal_samples <= 0 || backing_samples <= 0 || vocal_rate != backing_rate) { + free(vocal); + free(instrumental); + if (error) *error = "could not analyze separated stems for automatic vocal balance"; + return false; + } + const int length = std::min(vocal_samples, backing_samples); + const int window = std::max(1, vocal_rate * 2 / 5); // 400 ms level-analysis windows + float peak_vocal_rms = 0.0f; + for (int start = 0; start < length; start += window) { + const int count = std::min(window, length - start); + double energy = 0.0; + for (int i = 0; i < count; i++) { + const double l = vocal[(size_t) start + i]; + const double r = vocal[(size_t) vocal_samples + start + i]; + energy += l * l + r * r; + } + peak_vocal_rms = std::max(peak_vocal_rms, (float) std::sqrt(energy / (2.0 * count))); + } + const float vocal_gate = std::max(0.0005f, peak_vocal_rms * 0.08f); + std::vector ratios; + for (int start = 0; start < length; start += window) { + const int count = std::min(window, length - start); + double vocal_energy = 0.0, backing_energy = 0.0; + for (int i = 0; i < count; i++) { + const size_t left = (size_t) start + i; + const size_t right_v = (size_t) vocal_samples + left; + const size_t right_b = (size_t) backing_samples + left; + const double vl = vocal[left], vr = vocal[right_v]; + const double bl = instrumental[left], br = instrumental[right_b]; + vocal_energy += vl * vl + vr * vr; + backing_energy += bl * bl + br * br; + } + const float vrms = (float) std::sqrt(vocal_energy / (2.0 * count)); + const float brms = (float) std::sqrt(backing_energy / (2.0 * count)); + if (vrms >= vocal_gate && brms > 0.0001f) ratios.push_back(20.0f * std::log10(vrms / brms)); + } + free(vocal); + free(instrumental); + if (ratios.empty()) { + if (error) *error = "could not find active vocal passages for automatic balance; try the manual gain"; + return false; + } + const size_t mid = ratios.size() / 2; + std::nth_element(ratios.begin(), ratios.begin() + mid, ratios.end()); + const float median_ratio_db = ratios[mid]; + // A conservative starting point: vocals slightly ahead of the backing + // in sections where the vocal stem is active. This is a heuristic, not + // a universal mix standard; the user can still fine-tune the result. + vocal_gain_db = std::clamp(1.0f - median_ratio_db, -6.0f, 6.0f); + } + char gain[64]; + snprintf(gain, sizeof(gain), "volume=%.6fdB", (double) vocal_gain_db); + std::string vocal_arg = vocals.string(); + std::string backing_arg = backing.string(); + std::string output_arg = output.string(); + std::string rate = std::to_string(sample_rate); + std::vector remix = {"ffmpeg", "-hide_banner", "-nostdin", "-y", "-loglevel", "error", + "-i", backing_arg, "-i", vocal_arg, "-filter_complex", + std::string("[1:a]") + gain + "[v];[0:a][v]amix=inputs=2:duration=longest:normalize=0,alimiter=limit=0.98:latency=1,aresample=" + rate + ",apad=whole_len=" + std::to_string(samples) + ",atrim=end_sample=" + std::to_string(samples) + ",asetpts=PTS-STARTPTS[out]", + "-map", "[out]", "-ar", rate, "-c:a", "pcm_f32le", output_arg}; + const int ffmpeg_status = audio_vocal_run("ffmpeg", remix); + if (ffmpeg_status != 0) { + if (error) *error = ffmpeg_status == -1 + ? "FFmpeg was not found. Install FFmpeg and add it to PATH, then restart YuE2." + : "FFmpeg could not remix the stems. Check that FFmpeg is available on PATH and the separated WAV files are readable."; + return false; + } + int result_samples = 0, result_rate = 0; + float * decoded = audio_io_read_wav(output.string().c_str(), &result_samples, &result_rate); + if (!decoded) { + if (error) *error = "FFmpeg did not produce readable remixed audio"; + return false; + } + if (result_samples != samples || result_rate != sample_rate) { + free(decoded); + if (error) *error = "remixed audio format changed unexpectedly"; + return false; + } + balanced->assign(decoded, decoded + (size_t) result_samples * 2); + free(decoded); + if (applied_gain_db) *applied_gain_db = vocal_gain_db; + return true; +} diff --git a/src/job-archive.h b/src/job-archive.h new file mode 100644 index 0000000..1afd7cb --- /dev/null +++ b/src/job-archive.h @@ -0,0 +1,77 @@ +#pragma once +#include +#include +#include +#include +#include + +// Immutable terminal records: atomic rename publishes metadata and audio together. +// Unacknowledged results are never automatically removed. Acknowledged results +// remain recoverable for 30 days. In-flight native computation cannot resume; +// its pending marker becomes an explicit interrupted status after restart. +namespace job_archive { +namespace fs = std::filesystem; +inline bool valid_id(const std::string & id) { + if (id.size() != 16 && id.size() != 32) return false; + return id.find_first_not_of("0123456789abcdef") == std::string::npos; +} +inline fs::path root() { return fs::absolute("job_results"); } +inline fs::path path(const std::string & id, const char * suffix) { + if (!valid_id(id)) throw std::runtime_error("Invalid job ID"); + return root() / (id + suffix); +} +inline void start(const std::string & id) { + fs::create_directories(root()); + uintmax_t bytes=0; + for(const auto &entry:fs::directory_iterator(root()))if(entry.is_regular_file())bytes+=entry.file_size(); + if(bytes>16ULL*1024*1024*1024)throw std::runtime_error("Job recovery storage exceeds 16 GiB. Back up saved tracks and review job_results before starting more work."); + if(fs::space(root()).available<512ULL*1024*1024)throw std::runtime_error("Less than 512 MiB disk space remains. Free space before generating more media."); + std::ofstream out(path(id,".pending"), std::ios::binary); + out << "interrupted\n"; out.flush(); + if (!out) throw std::runtime_error("Cannot save job recovery record; check disk space and permissions"); +} +inline void finish(const std::string & id, int status, const std::string & mime, const std::string & body) { + fs::create_directories(root()); + const auto temp = path(id,".tmp"), result = path(id,".result"); + if (fs::exists(result)) return; + { + std::ofstream out(temp,std::ios::binary | std::ios::trunc); + out << "YUE2JOB1\n" << status << '\n' << mime.size() << '\n' << body.size() << '\n'; + out.write(mime.data(), (std::streamsize)mime.size()); + out.write(body.data(), (std::streamsize)body.size()); out.flush(); + if (!out) throw std::runtime_error("Cannot save completed job; disk full or unavailable"); + } + fs::rename(temp,result); + std::error_code error; fs::remove(path(id,".pending"),error); +} +inline bool read(const std::string & id, int & status, std::string & mime, std::string & body, bool include_body) { + if (!valid_id(id)) return false; + std::ifstream in(path(id,".result"),std::ios::binary); + if (!in) { if (fs::exists(path(id,".pending"))) { status = 4; return true; } return false; } + std::string magic; std::getline(in,magic); + uint64_t mime_size = 0, body_size = 0; + in >> status >> mime_size >> body_size; in.get(); + if (!in || magic != "YUE2JOB1" || status < 1 || status > 3 || mime_size > 4096) throw std::runtime_error("Corrupt archived job metadata"); + const auto offset = in.tellg(); + const uint64_t size = fs::file_size(path(id,".result")); + if (offset < 0 || (uint64_t)offset > size || mime_size > size - (uint64_t)offset || body_size != size - (uint64_t)offset - mime_size) throw std::runtime_error("Incomplete archived job"); + mime.resize((size_t)mime_size); in.read(mime.data(), (std::streamsize)mime_size); + if (include_body) { body.resize((size_t)body_size); in.read(body.data(), (std::streamsize)body_size); } + if (!in) throw std::runtime_error("Cannot read archived job"); + return true; +} +inline void acknowledge(const std::string & id) { + if (!fs::exists(path(id,".result"))) return; + std::ofstream out(path(id,".ack")); out << "saved to library\n"; out.flush(); + if (!out) throw std::runtime_error("Cannot record result acknowledgement"); +} +inline void cleanup() { + if (!fs::exists(root())) return; + for (const auto & entry : fs::directory_iterator(root())) { + if (entry.path().extension() != ".ack" || !valid_id(entry.path().stem().string())) continue; + if (fs::file_time_type::clock::now() - entry.last_write_time() < std::chrono::hours(24 * 30)) continue; + const auto id = entry.path().stem().string(); + for (const char * suffix : {".result", ".pending", ".tmp", ".ack"}) { std::error_code error; fs::remove(path(id,suffix),error); } + } +} +} diff --git a/src/pipeline.h b/src/pipeline.h index 76b0f3f..b0e4c1d 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -1,4 +1,5 @@ #pragma once +#include // pipeline.h: YuE2 generation pipeline // // Turns one request into tracks: a symbolic plan, a semantic token stream, @@ -49,6 +50,7 @@ struct Yue2PipelineParams { }; struct Yue2Pipeline { + std::function progress; ModelStore * store = nullptr; // borrowed, owned by the tool std::string model_path; // the backbone GGUF, both halves and the tokenizer std::string vae_path; @@ -277,6 +279,7 @@ static bool pipeline_generate(Yue2Pipeline * p, abc_ids.assign(B, encode(r.abc)); scores.assign(B, r.abc); } else if (has_score) { + if(p->progress) p->progress("Composing score",0,0); std::vector open = yue2_build_prompt_ids(encode, cot, r.style, r.lyrics, nullptr); std::vector plans; if (!yue2_generate(lm, &p->kv, std::vector>(B, open), {}, 1.0f, r.abc_sampling, r.lm_seed, @@ -318,12 +321,23 @@ static bool pipeline_generate(Yue2Pipeline * p, codes[0].truncated = false; fprintf(stderr, "[Pipeline] Replay: %zu frames supplied\n", codes[0].tokens.size()); } else { + if(p->progress) p->progress("Composing performance",0,0); + float duration = r.duration; + if (duration <= 0.0f) { + duration = yue2_estimate_duration_from_lyrics(r.lyrics); + if (duration > 0.0f) { + fprintf(stderr, "[Pipeline] Auto duration from lyrics: %.1f s\n", (double) duration); + } else { + duration = 360.0f; + fprintf(stderr, "[Pipeline] No lyrics, using default duration: %.1f s\n", (double) duration); + } + } // The requested length caps the budget of the stage, never raises it Yue2Sampling semantic = r.semantic_sampling; - int budget = (int) (r.duration * (float) YUE2_FRAME_RATE); + int budget = (int) (duration * (float) YUE2_FRAME_RATE); if (budget > 0 && budget < semantic.max_tokens) { - fprintf(stderr, "[AR] Frame budget clamped to %d by the requested duration (%.1f s)\n", budget, - (double) r.duration); + fprintf(stderr, "[AR] Frame budget clamped to %d by the %s duration (%.1f s)\n", budget, + r.duration <= 0.0f ? "auto" : "requested", (double) duration); semantic.max_tokens = budget; if (semantic.min_tokens > semantic.max_tokens) { semantic.min_tokens = semantic.max_tokens; @@ -402,10 +416,12 @@ static bool pipeline_generate(Yue2Pipeline * p, const int chunk_size = chunk_sizes[i]; const int T_lat = (int) codes[i].tokens.size(); int chunks = (T_lat + chunk_size - 1) / chunk_size; + if(p->progress) p->progress("Rendering audio",i,B); fprintf(stderr, "[NAR] Song %d: %d frames (%.1f s), prefix %d, %d chunk%s of %d, %d variation%s\n", i, T_lat, (float) T_lat / (float) YUE2_FRAME_RATE, prefix_len, chunks, chunks > 1 ? "s" : "", chunk_size, M, M > 1 ? "s" : ""); for (int start = 0; start < T_lat; start += chunk_size) { + if(p->progress) p->progress("Rendering audio chunks",start/chunk_size,chunks); Timer chunk_timer; int frames = T_lat - start < chunk_size ? T_lat - start : chunk_size; int ar_len = prefix_len + frames + 1; @@ -467,6 +483,7 @@ static bool pipeline_generate(Yue2Pipeline * p, } nar_hold.reset(); + if(p->progress) p->progress("Decoding audio",0,0); VAEGGML * vae = require_vae(p); if (!vae) { return false; diff --git a/src/prompt.h b/src/prompt.h index 6f11f42..79f7ee5 100644 --- a/src/prompt.h +++ b/src/prompt.h @@ -135,3 +135,30 @@ static std::vector yue2_build_negative_ids(Tokenize bpe_encode, Yue2Cot cot static float yue2_default_guidance(Yue2Cot cot) { return cot == YUE2_COT_OFF ? 1.01f : 1.0f; } + +// Estimate song duration in seconds from lyrics text. +// Heuristic: ~140 words/minute singing rate + 30s for intro/outro/instrumentals. +// Returns 0 if lyrics are empty (caller should use default). +static float yue2_estimate_duration_from_lyrics(const std::string & lyrics) { + if (lyrics.empty()) { + return 0.0f; + } + int words = 0; + bool in_word = false; + for (char c : lyrics) { + if (c == ' ' || c == '\n' || c == '\r' || c == '\t') { + in_word = false; + } else if (!in_word) { + in_word = true; + words++; + } + } + if (words == 0) { + return 0.0f; + } + float minutes = (float) words / 140.0f; + float seconds = minutes * 60.0f + 30.0f; + if (seconds < 30.0f) seconds = 30.0f; + if (seconds > 600.0f) seconds = 600.0f; + return seconds; +} diff --git a/src/request.cpp b/src/request.cpp index 3f97ab0..4e50680 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -35,7 +35,8 @@ void request_init(Yue2Request * r) { r->semantic_sampling = YUE2_SEMANTIC_SAMPLING; r->output_format = OUTPUT_FORMAT_MP3; - r->mp3_bitrate = 128; + r->mp3_bitrate = 320; + r->mastering_profile = "off"; } static inline std::string yy_str(yyjson_val * v) { @@ -162,6 +163,9 @@ static void request_parse_obj(yyjson_val * obj, Yue2Request * r) { if ((v = yyjson_obj_get(obj, "mp3_bitrate")) && yyjson_is_int(v)) { r->mp3_bitrate = yyjson_get_int(v); } + if ((v = yyjson_obj_get(obj, "mastering_profile")) && yyjson_is_str(v)) { + r->mastering_profile = yy_str(v); + } } bool request_parse_json(Yue2Request * r, const char * json) { @@ -256,6 +260,9 @@ std::string request_to_json(const Yue2Request * r, bool sparse) { if (!sparse || r->mp3_bitrate != d.mp3_bitrate) { yyjson_mut_obj_add_int(doc, root, "mp3_bitrate", r->mp3_bitrate); } + if (!sparse || r->mastering_profile != d.mastering_profile) { + yyjson_mut_obj_add_strncpy(doc, root, "mastering_profile", r->mastering_profile.c_str(), r->mastering_profile.size()); + } char * json = yyjson_mut_write(doc, WRITE_FLAGS, NULL); std::string out = json ? json : "{}"; diff --git a/src/request.h b/src/request.h index 213e5b9..1ffb0bc 100644 --- a/src/request.h +++ b/src/request.h @@ -69,6 +69,7 @@ struct Yue2Request { // MP3 encoder bitrate in kbps, used when output_format is "mp3". // WAV outputs ignore this field. int mp3_bitrate; // 128 + std::string mastering_profile; // "off", "streaming" or "broadcast" }; // fills every field with its default diff --git a/src/saved-presets.h b/src/saved-presets.h new file mode 100644 index 0000000..6696709 --- /dev/null +++ b/src/saved-presets.h @@ -0,0 +1,98 @@ +#pragma once +#include "httplib.h" +#include "yyjson.h" +#include +#include +#include +#include + +inline void register_saved_presets(httplib::Server & server) { + namespace fs = std::filesystem; + const auto folder = fs::absolute("saved_presets"); + // Reconcile an interrupted replacement before listing or accepting writes. + fs::create_directories(folder); + for (const auto & entry : fs::directory_iterator(folder)) { + if (fs::is_symlink(entry.path())) continue; + const auto ext=entry.path().extension(); + if (ext != ".bak" && ext != ".tmp") continue; + auto final=entry.path(); final.replace_extension(".json"); + if (ext == ".bak" && !fs::exists(final)) fs::rename(entry.path(),final); + else fs::remove(entry.path()); + } + auto mutex = std::make_shared(); + server.Get("/presets", [folder, mutex](const httplib::Request &, httplib::Response & res) { + std::lock_guard lock(*mutex); + try { + fs::create_directories(folder); + std::string body = "["; + for (const auto & file : fs::directory_iterator(folder)) { + if (!file.is_regular_file() || file.path().extension() != ".json" || fs::is_symlink(file.path())) continue; + std::ifstream input(file.path(), std::ios::binary); + std::string value((std::istreambuf_iterator(input)), {}); + auto * doc = yyjson_read(value.data(), value.size(), 0); + if (!doc) continue; + auto * root = yyjson_doc_get_root(doc); + const bool valid = yyjson_is_obj(root) && yyjson_is_str(yyjson_obj_get(root,"name")) && yyjson_is_str(yyjson_obj_get(root,"kind")) && yyjson_is_obj(yyjson_obj_get(root,"data")); + if (valid) { + // Filename is authoritative after atomic rename. + auto mutable_doc=yyjson_doc_mut_copy(doc,nullptr); + auto mutable_root=yyjson_mut_doc_get_root(mutable_doc); + const auto stem=file.path().stem().u8string(); + const auto dash=stem.find('-'); + const auto name=stem.substr(dash+1); + yyjson_mut_obj_put(mutable_root,yyjson_mut_strcpy(mutable_doc,"name"),yyjson_mut_strcpy(mutable_doc,name.c_str())); + char * encoded=yyjson_mut_write(mutable_doc,0,nullptr); + if(encoded) { value=encoded; free(encoded); } + yyjson_mut_doc_free(mutable_doc); + } + yyjson_doc_free(doc); + if (valid) { if (body.size() > 1) body += ','; body += value; } + } + res.set_content(body + "]", "application/json"); + } catch (...) { res.status = 500; res.set_content("Could not read saved_presets folder", "text/plain"); } + }); + server.Post("/presets", [folder, mutex](const httplib::Request & req, httplib::Response & res) { + std::lock_guard lock(*mutex); + if (req.get_header_value("Content-Type").find("application/json") != 0 || req.body.size() > 262144) { res.status = 400; return; } + auto * doc = yyjson_read(req.body.data(), req.body.size(), 0); + if (!doc) { res.status = 400; return; } + auto * root = yyjson_doc_get_root(doc); + auto str = [&](const char * key) { const char * s = yyjson_get_str(yyjson_obj_get(root,key)); return std::string(s ? s : ""); }; + const auto name = str("name"), kind = str("kind"), operation = str("operation"); + auto * data = yyjson_obj_get(root,"data"); + const bool overwrite = yyjson_get_bool(yyjson_obj_get(root,"overwrite")); + bool valid = !name.empty() && name.size() <= 200 && name.back() != '.' && name.back() != ' ' && (kind == "music" || kind == "lyric" || kind == "studio") && (operation == "save" || operation == "delete" || operation == "rename"); + for (unsigned char c : name) if (c < 32 || std::string("<>:\"/\\|?*").find(c) != std::string::npos) valid = false; + if (operation == "save" && (!yyjson_is_obj(data) || !yyjson_is_arr(yyjson_obj_get(data,"ids")) || !yyjson_is_obj(yyjson_obj_get(data,"weights")))) valid = false; + if (!valid) { yyjson_doc_free(doc); res.status = 400; res.set_content("Use a preset name without filename characters or trailing dots/spaces.","text/plain"); return; } + try { + fs::create_directories(folder); + const auto file = folder / fs::u8path(kind + "-" + name + ".json"); + if (fs::is_symlink(file)) throw std::runtime_error("Invalid preset file"); + if (operation == "rename") { + const auto old_name=str("oldName"); + bool safe=!old_name.empty() && old_name.size()<=200 && old_name.back()!='.' && old_name.back()!=' '; + for(unsigned char c:old_name) if(c<32 || std::string("<>:\\\"/\\\\|?*").find(c)!=std::string::npos) safe=false; + if(!safe) throw std::runtime_error("Invalid original preset name"); + const auto source=folder / fs::u8path(kind+"-"+old_name+".json"); + if(fs::is_symlink(source) || !fs::exists(source)) throw std::runtime_error("Original preset no longer exists"); + if(fs::exists(file)) { res.status=409; res.set_content("Preset name already exists","text/plain"); yyjson_doc_free(doc); return; } + fs::rename(source,file); + } + else if (operation == "delete") fs::remove(file); + else if (fs::exists(file) && !overwrite) { res.status = 409; res.set_content("A preset with that name already exists.","text/plain"); yyjson_doc_free(doc); return; } + else { + const auto temp = folder / fs::u8path(kind + "-" + name + ".tmp"); + const auto backup = folder / fs::u8path(kind + "-" + name + ".bak"); + if (fs::is_symlink(temp) || fs::exists(backup)) throw std::runtime_error("Preset has a pending recovery file"); + { std::ofstream out(temp, std::ios::binary | std::ios::trunc); out << req.body; out.flush(); if (!out) throw std::runtime_error("Could not write preset"); } + const bool existed = fs::exists(file); + if (existed) fs::rename(file, backup); + try { fs::rename(temp, file); } catch (...) { if (existed) fs::rename(backup,file); throw; } + if (existed) fs::remove(backup); + } + res.set_content("{\"ok\":true}","application/json"); + } catch (const std::exception & e) { res.status = 500; res.set_content(e.what(),"text/plain"); } + yyjson_doc_free(doc); + }); +} diff --git a/tests/archive-native.mjs b/tests/archive-native.mjs new file mode 100644 index 0000000..e420691 --- /dev/null +++ b/tests/archive-native.mjs @@ -0,0 +1,6 @@ +import {spawnSync} from 'node:child_process'; +import {join} from 'node:path'; +import {fileURLToPath} from 'node:url'; +const root=fileURLToPath(new URL('../',import.meta.url)); +const env=process.platform==='win32'?Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v])):process.env; +for(const [cmd,args] of [['cmake',['-S','tests/job-archive','-B','build/job-archive-tests']],['cmake',['--build','build/job-archive-tests','--config','Release']],[join(root,'build/job-archive-tests',process.platform==='win32'?'Release/job-archive-test.exe':'job-archive-test'),[]]]){const r=spawnSync(cmd,args,{cwd:root,env,stdio:'inherit',windowsHide:true});if(r.status!==0)process.exit(r.status??1);} diff --git a/tests/job-archive/CMakeLists.txt b/tests/job-archive/CMakeLists.txt new file mode 100644 index 0000000..7b15d8b --- /dev/null +++ b/tests/job-archive/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.16) +project(job_archive_test LANGUAGES CXX) +add_executable(job-archive-test main.cpp) +target_compile_features(job-archive-test PRIVATE cxx_std_17) +target_include_directories(job-archive-test PRIVATE ../../src) +if(MSVC) + target_compile_options(job-archive-test PRIVATE /EHsc) +endif() diff --git a/tests/job-archive/main.cpp b/tests/job-archive/main.cpp new file mode 100644 index 0000000..b99e455 --- /dev/null +++ b/tests/job-archive/main.cpp @@ -0,0 +1,25 @@ +#include "job-archive.h" +#include + +static void check(bool value, const char * message) { if (!value) throw std::runtime_error(message); } +int main() { + namespace fs = std::filesystem; + const auto sandbox = fs::absolute("build/job-archive-tests/work-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); + fs::create_directories(sandbox); fs::current_path(sandbox); + const std::string id = "0123456789abcdef0123456789abcdef"; + check(!job_archive::valid_id("../invalid"),"invalid IDs accepted"); + job_archive::start(id); + int status = 0; std::string mime,body; + check(job_archive::read(id,status,mime,body,false) && status == 4,"pending jobs must recover as interrupted"); + const std::string original("binary\0audio",12); + job_archive::finish(id,1,"audio/wav",original); + check(job_archive::read(id,status,mime,body,false) && status == 1 && body.empty(),"metadata polling must not load audio"); + check(job_archive::read(id,status,mime,body,true) && body == original && mime == "audio/wav","archived binary mismatch"); + job_archive::finish(id,2,"", "different"); + check(job_archive::read(id,status,mime,body,true) && status == 1 && body == original,"terminal records must be immutable"); + job_archive::cleanup(); check(fs::exists(job_archive::path(id,".result")),"unacknowledged result removed"); + job_archive::acknowledge(id); + fs::last_write_time(job_archive::path(id,".ack"),fs::file_time_type::clock::now()-std::chrono::hours(24*31)); + job_archive::cleanup(); check(!fs::exists(job_archive::path(id,".result")),"expired acknowledged result retained"); + std::cout << "PASS: pending restart, binary persistence, metadata-only polling, idempotence, acknowledgement retention, safe IDs\n"; +} diff --git a/tests/media-followup.mjs b/tests/media-followup.mjs new file mode 100644 index 0000000..52c9699 --- /dev/null +++ b/tests/media-followup.mjs @@ -0,0 +1,25 @@ +// Manual real-media check; requires an idle Studio and existing real-media artifacts. +import {readFile,writeFile} from 'node:fs/promises'; +import {execFileSync} from 'node:child_process'; +import {availableArtModels,artworkGraph} from '../tools/webui/src/lib/comfy-art.ts'; +const base='http://127.0.0.1:8087',folder='build/media-acceptance/',report=JSON.parse(await readFile('build/media-acceptance/followup.json','utf8').catch(()=>'[]')); +async function json(path,init){const r=await fetch(base+path,init);if(!r.ok)throw Error(path+': '+await r.text());return r.json();} +async function record(name,data){report.push({name,data,at:new Date().toISOString()});console.log(name,JSON.stringify(data));await writeFile(folder+'followup.json',JSON.stringify(report,null,2));} +async function poll(id){for(let n=0;n<900;n++){const s=await json('/job?id='+id);if(s.status==='done')return;if(s.status!=='running')throw Error(JSON.stringify(s));if(n%15===0)console.log(await json('/jobs'));await new Promise(r=>setTimeout(r,2000));}throw Error('Job timeout');} +try{ + const cover=await readFile(folder+'cover.png'); + if(!process.argv.includes('--skip-reference')){ + const form=new FormData();form.append('image',new Blob([cover],{type:'image/png'}),'reference-check.png');form.append('type','input'); + const image=await json('/comfy/upload/image',{method:'POST',body:form}); + const models=availableArtModels(await json('/comfy/object_info')); + const graph=artworkGraph(models,'Create an entirely NEW scene using only the illustration medium, amber lighting and purple color palette from . Replace the man, street and bridge completely. Show a close-up vintage drum machine and vinyl records on a rooftop table at sunset, distant city skyline. No people. No bridge. No lettering.',112346,'yue2-reference-check',(image.subfolder?image.subfolder+'/':'')+image.name+' [input]'); + const started=Date.now(),{prompt_id}=await json('/comfy/prompt',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:graph})});await record('Reference retry submitted',{prompt_id,cfg:4}); + for(let n=0;n<900;n++){const h=(await json('/comfy/history/'+prompt_id))[prompt_id];if(h?.status?.status_str==='error')throw Error(JSON.stringify(h.status));const img=h?.outputs?.['8']?.images?.[0];if(img){const r=await fetch(base+'/comfy/view?'+new URLSearchParams(img));await writeFile(folder+'reference-cover-guided.png',Buffer.from(await r.arrayBuffer()));await record('Reference retry completed',{seconds:(Date.now()-started)/1000});break;}if(n%15===0)console.log('Reference artwork processing');await new Promise(r=>setTimeout(r,2000));} + } + const form=new FormData();form.append('audio',new Blob([await readFile(folder+'take-0.wav')],{type:'audio/wav'}),'original.wav');form.append('vocal_gain_db','3'); + const start=Date.now(),{id}=await json('/vocal-balance',{method:'POST',body:form});await record('Vocal separation submitted',{id});await poll(id);const r=await fetch(base+'/job?id='+id+'&result=1');await writeFile(folder+'vocal-plus3.wav',Buffer.from(await r.arrayBuffer()));await record('Vocal separation completed',{seconds:(Date.now()-start)/1000,contentType:r.headers.get('Content-Type')}); + await fetch(base+'/job?id='+id+'&ack=1',{method:'POST'}); + const delivery=new FormData();delivery.append('audio',new Blob([await readFile(folder+'take-1.wav')],{type:'audio/wav'}),'master.wav');delivery.append('cover',new Blob([cover],{type:'image/png'}),'cover.png'); + const video=await json('/render-video',{method:'POST',body:delivery});await poll(video.id);await writeFile(folder+'hiphop-circuit-test.mp4',Buffer.from(await(await fetch(base+'/job?id='+video.id+'&result=1')).arrayBuffer()));await fetch(base+'/job?id='+video.id+'&ack=1',{method:'POST'}); + const probe=JSON.parse(execFileSync('ffprobe',['-v','error','-show_streams','-of','json',folder+'hiphop-circuit-test.mp4'],{encoding:'utf8',windowsHide:true}));await record('MP4 codecs',probe.streams.map(s=>({codec:s.codec_name,width:s.width,height:s.height,duration:s.duration}))); +}catch(e){await record('Needs attention',{error:String(e)});process.exitCode=1;} diff --git a/tests/media-playback-browser.mjs b/tests/media-playback-browser.mjs new file mode 100644 index 0000000..79b7667 --- /dev/null +++ b/tests/media-playback-browser.mjs @@ -0,0 +1,10 @@ +// Manual: pass the path of a generated MP4, optionally its expected duration. +import {chromium} from '../tools/youtube-agent/node_modules/playwright/index.mjs'; +import {readFile} from 'node:fs/promises'; +import http from 'node:http'; +import {once} from 'node:events'; +import assert from 'node:assert/strict'; +const bytes=await readFile(process.argv[2]),expected=Number(process.argv[3]); +const server=http.createServer((req,res)=>{const range=req.headers.range?.match(/bytes=(\d+)-(\d*)/);const start=range?Number(range[1]):0,end=range&&range[2]?Math.min(Number(range[2]),bytes.length-1):bytes.length-1;res.writeHead(range?206:200,{'Content-Type':'video/mp4','Accept-Ranges':'bytes','Content-Length':end-start+1,...(range?{'Content-Range':`bytes ${start}-${end}/${bytes.length}`}:{})});res.end(bytes.subarray(start,end+1));});server.listen(0,'127.0.0.1');await once(server,'listening'); +const browser=await chromium.launch({...(process.env.CI?{}:{channel:'msedge'}),headless:true}); +try{const page=await browser.newPage();await page.setContent(``);await page.waitForFunction(()=>document.querySelector('video').readyState>=2);const duration=await page.locator('video').evaluate(v=>v.duration);if(expected)assert.ok(Math.abs(duration-expected)<1);await page.locator('video').evaluate(v=>v.play());await page.waitForFunction(()=>document.querySelector('video').currentTime>.1);await page.locator('video').evaluate(v=>{v.currentTime=v.duration-1;});await page.waitForFunction(()=>document.querySelector('video').ended,{},{timeout:10000});assert.equal(await page.locator('video').evaluate(v=>v.error),null);console.log('PASS: MP4 browser metadata, playback, end seek and completion.',{duration});}finally{await browser.close();server.close();} diff --git a/tests/media-queue.mjs b/tests/media-queue.mjs new file mode 100644 index 0000000..32d2865 --- /dev/null +++ b/tests/media-queue.mjs @@ -0,0 +1,38 @@ +import {spawn,execFileSync} from 'node:child_process'; +import {once} from 'node:events'; +import {mkdtemp,mkdir,writeFile,readFile} from 'node:fs/promises'; +import {fileURLToPath} from 'node:url'; +import {join} from 'node:path'; +import assert from 'node:assert/strict'; +const duration=process.argv.includes('--long')?360:3; +const root=fileURLToPath(new URL('../',import.meta.url)),work=await mkdtemp(join(root,'build/media-queue-')); +const env=Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v]));env.GGML_BACKEND='CPU'; +const run=(cmd,args)=>execFileSync(cmd,args,{cwd:work,env,windowsHide:true,encoding:'utf8',stdio:['ignore','pipe','pipe']}); +run('ffmpeg',['-y','-f','lavfi','-i',`sine=frequency=440:duration=${duration}`,'-ar','48000',join(work,'tone.wav')]); +run('ffmpeg',['-y','-f','lavfi','-i','color=c=purple:s=128x128','-frames:v','1',join(work,'cover.png')]); +await mkdir(join(work,'saved_presets')); +const preset={name:'Recovered',kind:'music',data:{ids:[],weights:{},prompt:'Jazz'}}; +await writeFile(join(work,'saved_presets/music-Recovered.bak'),JSON.stringify(preset)); +await writeFile(join(work,'saved_presets/music-Recovered.tmp'),'incomplete'); +const child=spawn(join(root,'build/Release-producer/yue-server.exe'),['--host','127.0.0.1','--port','18088','--comfy-port','18188','--max-seq','512','--model',join(root,'models/YuE2-3B-Q8_0.gguf'),'--vae',join(root,'models/YuE2-Vae-F32.gguf')],{cwd:work,env,windowsHide:true,stdio:['ignore','pipe','pipe']}); +let logs='';child.stderr.on('data',b=>logs+=b);child.stdout.on('data',()=>{}); +const base='http://127.0.0.1:18088'; +async function done(id){for(let i=0;i<2400;i++){const s=await(await fetch(base+`/job?id=${id}`)).json();if(s.status==='done'||s.status==='cancelled'||s.status==='failed')return s.status;await new Promise(r=>setTimeout(r,250));}throw Error('Media timeout '+logs);} +function form(audio,cover){const f=new FormData();f.append('audio',new Blob([audio],{type:'audio/wav'}),'tone.wav');f.append('cover',new Blob([cover],{type:'image/png'}),'cover.png');return f;} +try{ + for(let i=0;i<100;i++){try{if((await fetch(base+'/health')).ok)break;}catch{}await new Promise(r=>setTimeout(r,100));} + assert.equal((await(await fetch(base+'/presets')).json())[0].name,'Recovered'); + assert.equal((await fetch(base+'/presets',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({...preset,name:'Renamed',oldName:'Recovered',operation:'rename'})})).status,200); + assert.equal((await(await fetch(base+'/presets')).json())[0].name,'Renamed'); + const audio=await readFile(join(work,'tone.wav')),cover=await readFile(join(work,'cover.png')); + const id='22222222222222222222222222222222'; + const response=await fetch(base+'/render-video',{method:'POST',headers:{'X-Yue2-Job-Id':id},body:form(audio,cover)}); + assert.equal(response.status,200);assert.equal((await response.json()).id,id);assert.equal(await done(id),'done',logs); + const video=Buffer.from(await(await fetch(base+`/job?id=${id}&result=1`)).arrayBuffer());await writeFile(join(work,'video.mp4'),video); + const probe=JSON.parse(run('ffprobe',['-v','error','-show_streams','-of','json',join(work,'video.mp4')])); + assert.ok(probe.streams.some(s=>s.codec_name==='h264'&&s.width===1920&&s.height===1080));assert.ok(probe.streams.some(s=>s.codec_name==='aac'));assert.ok(Math.abs(Number(probe.streams[0].duration)-duration)<1); + const retry=await fetch(base+'/render-video',{method:'POST',headers:{'X-Yue2-Job-Id':id},body:form(audio,cover)});assert.equal((await retry.json()).id,id);assert.equal(await done(id),'done'); + const cancelId='33333333333333333333333333333333';await fetch(base+'/render-video',{method:'POST',headers:{'X-Yue2-Job-Id':cancelId},body:form(audio,cover)});await fetch(base+`/job?id=${cancelId}&cancel=1`,{method:'POST'});assert.equal(await done(cancelId),'cancelled'); + assert.deepEqual(await(await fetch(base+'/jobs')).json(),[]); + console.log('PASS: interrupted preset recovery; atomic rename; bounded asynchronous video, idempotent retry, H.264 1920x1080 + AAC, owned cancellation; '+duration+' seconds. '+work); +}finally{if(child.exitCode===null&&child.signalCode===null){const exit=once(child,'exit');child.kill();await exit;}} diff --git a/tests/real-media.mjs b/tests/real-media.mjs new file mode 100644 index 0000000..f1a5d13 --- /dev/null +++ b/tests/real-media.mjs @@ -0,0 +1,39 @@ +// Explicit manual acceptance run: uses the local GPU and ComfyUI, saves artifacts. +import {spawn,execFileSync} from 'node:child_process'; +import {once} from 'node:events'; +import {mkdir,readFile,writeFile,copyFile} from 'node:fs/promises'; +import {fileURLToPath} from 'node:url'; +import {join} from 'node:path'; +import assert from 'node:assert/strict'; +const root=fileURLToPath(new URL('../',import.meta.url)),work=join(root,'build/media-acceptance');await mkdir(work,{recursive:true}); +const bin=join(root,'build/Release-acceptance');await mkdir(bin,{recursive:true});for(const f of ['yue-server.exe','ggml.dll','ggml-base.dll','ggml-cpu.dll','ggml-cuda.dll'])await copyFile(join(root,'build/Release-producer',f),join(bin,f)); +const env=Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v]));env.PATH=join(root,'.venv-vocal/Scripts')+';'+bin+';'+env.PATH;delete env.GGML_BACKEND; +const server=spawn(join(bin,'yue-server.exe'),['--host','127.0.0.1','--port','18089','--max-seq','4096','--model',join(root,'models/YuE2-3B-Q8_0.gguf'),'--vae',join(root,'models/YuE2-Vae-F32.gguf')],{cwd:work,env,windowsHide:true,stdio:['ignore','pipe','pipe']}); +let logs='';server.stderr.on('data',b=>{logs+=b;});server.stdout.on('data',()=>{}); +const base='http://127.0.0.1:18089',report={started:new Date().toISOString(),checks:[],artifacts:work}; +async function checkpoint(name,details){report.checks.push({name,details,at:new Date().toISOString()});await writeFile(join(work,'report.json'),JSON.stringify(report,null,2));await writeFile(join(work,'server.log'),logs);console.log(name,JSON.stringify(details));} +async function poll(id){for(let i=0;i<1800;i++){const data=await(await fetch(base+`/job?id=${id}`)).json();if(data.status==='done')return;if(data.status!=='running')throw Error(JSON.stringify(data)+' '+logs.slice(-3000));if(i%15===0)console.log('Working',JSON.stringify(await(await fetch(base+'/jobs')).json()));await new Promise(r=>setTimeout(r,2000));}throw Error('Job timed out');} +const ff=(cmd,args)=>execFileSync(cmd,args,{env,windowsHide:true,encoding:'utf8',maxBuffer:16*1024*1024}); +function multipart(bytes,boundary){const marker=Buffer.from('--'+boundary),parts=[];let pos=bytes.indexOf(marker);for(;;){const next=bytes.indexOf(marker,pos+marker.length);if(next<0)break;const headerEnd=bytes.indexOf('\r\n\r\n',pos),header=bytes.subarray(pos,headerEnd).toString();parts.push({header,body:bytes.subarray(headerEnd+4,next-2)});pos=next;}return parts;} +async function imageJob(reference){const info=await(await fetch(base+'/comfy/object_info')).json();const {availableArtModels,artworkGraph}=await import('../tools/webui/src/lib/comfy-art.ts');const models=availableArtModels(info);let ref; + if(reference){const f=new FormData();f.append('image',new Blob([reference],{type:'image/png'}),'acceptance-reference.png');f.append('overwrite','false');const r=await(await fetch(base+'/comfy/upload/image',{method:'POST',body:f})).json();ref=(r.subfolder?r.subfolder+'/':'')+r.name+' [input]';} + const prompt=reference?'Use as a palette and illustration style reference. A different scene: a vintage drum machine on a rooftop at violet sunset, cinematic hip hop album cover, no text.':'Cinematic illustrated hip hop album cover: a lone adult rapper in a yellow jacket beneath a rain-soaked city overpass, warm amber streetlights and violet shadows, richly detailed, no text or logos.'; + const start=Date.now(),response=await fetch(base+'/comfy/prompt',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:artworkGraph(models,prompt,7217,reference?'yue2-acceptance-reference':'yue2-acceptance-cover',ref),client_id:'yue2-acceptance'})});if(!response.ok)throw Error(await response.text());const {prompt_id}=await response.json();await checkpoint('Artwork submitted',{prompt_id,reference:!!reference}); + for(let i=0;i<900;i++){const history=await(await fetch(base+'/comfy/history/'+prompt_id)).json(),item=history[prompt_id];if(item?.status?.status_str==='error')throw Error(JSON.stringify(item.status));const image=item?.outputs?.['8']?.images?.[0];if(image){const bytes=Buffer.from(await(await fetch(base+'/comfy/view?'+new URLSearchParams(image))).arrayBuffer());await checkpoint(reference?'Reference artwork completed':'Artwork completed',{seconds:(Date.now()-start)/1000,bytes:bytes.length});return bytes;}if(i%15===0)console.log('Artwork still processing',prompt_id);await new Promise(r=>setTimeout(r,2000));}throw Error('Artwork timeout');} +try{ + for(let i=0;i<100;i++){try{if((await fetch(base+'/health')).ok)break;}catch{}await new Promise(r=>setTimeout(r,200));} + const request={style:'Boom bap hip hop, 90 BPM, warm clear male mid-range rhythmic rap, dusty drums, jazz piano, deep bass, articulate delivery.',lyrics:'[Verse]\nCity lights are shining through the rain\nBuild a little rhythm from the train\nStep by step we find a brighter way\nTurn another midnight into day',cot:'off',duration:12,lm_seed:7217,seed:7217,lm_batch_size:1,synth_batch_size:2,steps:32,output_format:'wav24',mastering_profile:'streaming'}; + const start=Date.now(),id=crypto.randomUUID().replaceAll('-','');const response=await fetch(base+'/synth',{method:'POST',headers:{'Content-Type':'application/json','X-Yue2-Job-Id':id},body:JSON.stringify(request)});if(!response.ok)throw Error(await response.text());await checkpoint('Music submitted',{id,request});await poll(id); + const result=await fetch(base+`/job?id=${id}&result=1`),boundary=result.headers.get('Content-Type').match(/boundary=([^\s;]+)/)[1];const parts=multipart(Buffer.from(await result.arrayBuffer()),boundary);let audio,original,index=0; + for(const part of parts){if(part.header.includes('application/json')){await writeFile(join(work,`request-${index}.json`),part.body);continue;}await writeFile(join(work,`take-${index}.wav`),part.body);if(index===1)audio=part.body;if(index===0)original=part.body;index++;} + assert.equal(index,4,'two mastered takes paired with originals');await checkpoint('Real music completed',{seconds:(Date.now()-start)/1000,audioParts:index}); + const probe=JSON.parse(ff('ffprobe',['-v','error','-show_streams','-of','json',join(work,'take-0.wav')]));assert.equal(probe.streams[0].sample_rate,'48000');await checkpoint('Audio format',probe.streams[0]); + // Measure actual input loudness and peak without changing the saved audio. + for(const n of [0,1]){const proc=spawn('ffmpeg',['-hide_banner','-i',join(work,`take-${n}.wav`),'-af','loudnorm=I=-14:TP=-1:print_format=json','-f','null','-'],{env,windowsHide:true,stdio:['ignore','ignore','pipe']});let output='';proc.stderr.on('data',b=>output+=b);await once(proc,'exit');await writeFile(join(work,`loudness-${n}.txt`),output);await checkpoint('Loudness measured',{take:n,version:n===0?'original':'streaming master',measurement:output.slice(output.lastIndexOf('{'))});} + const cover=await imageJob();await writeFile(join(work,'cover.png'),cover); + const referenced=await imageJob(cover);await writeFile(join(work,'reference-cover.png'),referenced); + const form=new FormData();form.append('audio',new Blob([audio],{type:'audio/wav'}),'track.wav');form.append('cover',new Blob([cover],{type:'image/png'}),'cover.png');const videoId=(await(await fetch(base+'/render-video',{method:'POST',body:form})).json()).id;assert.ok(videoId);await poll(videoId);await writeFile(join(work,'hiphop-circuit-test.mp4'),Buffer.from(await(await fetch(base+`/job?id=${videoId}&result=1`)).arrayBuffer()));await checkpoint('Generated artwork MP4 ready',{videoId}); + const vocalForm=new FormData();vocalForm.append('audio',new Blob([original],{type:'audio/wav'}),'original.wav');vocalForm.append('vocal_gain_db','3');const vocalResponse=await fetch(base+'/vocal-balance',{method:'POST',body:vocalForm});if(!vocalResponse.ok)throw Error(await vocalResponse.text());const vocalId=(await vocalResponse.json()).id;await poll(vocalId);await writeFile(join(work,'vocal-plus3.wav'),Buffer.from(await(await fetch(base+`/job?id=${vocalId}&result=1`)).arrayBuffer()));await checkpoint('Real vocal separation completed',{vocalId}); + await checkpoint('Acceptance run finished',{ }); +}catch(error){await checkpoint('Acceptance needs attention',{error:String(error),log:logs.slice(-4000)});process.exitCode=1;} +finally{await writeFile(join(work,'server.log'),logs);if(server.exitCode===null&&server.signalCode===null){const ended=once(server,'exit');server.kill();await ended;}} diff --git a/tests/recovery-http.mjs b/tests/recovery-http.mjs new file mode 100644 index 0000000..1d1ce99 --- /dev/null +++ b/tests/recovery-http.mjs @@ -0,0 +1,35 @@ +import {spawn} from 'node:child_process'; +import {once} from 'node:events'; +import {mkdtemp,mkdir,writeFile} from 'node:fs/promises'; +import {fileURLToPath} from 'node:url'; +import {join} from 'node:path'; +import assert from 'node:assert/strict'; +const root=fileURLToPath(new URL('../',import.meta.url)); +const work=await mkdtemp(join(root,'build/recovery-http-')); +await mkdir(join(work,'job_results')); +const id='0123456789abcdef0123456789abcdef', interrupted='1111111111111111'; +const body=Buffer.from('archived\0audio'),mime='audio/wav'; +await writeFile(join(work,'job_results',id+'.result'),Buffer.concat([Buffer.from(`YUE2JOB1\n1\n${mime.length}\n${body.length}\n${mime}`),body])); +await writeFile(join(work,'job_results',interrupted+'.pending'),'interrupted\n'); +const env=Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v]));env.GGML_BACKEND='CPU'; +const base='http://127.0.0.1:18088';let child; +async function start(){ + child=spawn(join(root,'build/Release-producer/yue-server.exe'),['--host','127.0.0.1','--port','18088','--comfy-port','18188','--max-seq','512','--model',join(root,'models/YuE2-3B-Q8_0.gguf'),'--vae',join(root,'models/YuE2-Vae-F32.gguf')],{cwd:work,env,windowsHide:true,stdio:['ignore','pipe','pipe']}); + let logs='';child.stderr.on('data',b=>logs=(logs+b).slice(-8000)); + for(let i=0;i<100;i++){if(child.exitCode!==null)throw Error(logs);try{if((await fetch(base+'/health')).ok)return;}catch{}await new Promise(r=>setTimeout(r,200));}throw Error('Server startup timeout '+logs); +} +async function stop(){const stopping=child;child=undefined;if(stopping&&stopping.exitCode===null&&stopping.signalCode===null){const ended=once(stopping,'exit');stopping.kill();await ended;}} +try{ + for(let pass=0;pass<2;pass++){ + await start(); + assert.deepEqual(await(await fetch(base+`/job?id=${id}`)).json(),{status:'done',durable:true}); + assert.equal(Buffer.compare(Buffer.from(await(await fetch(base+`/job?id=${id}&result=1`)).arrayBuffer()),body),0); + assert.equal((await(await fetch(base+`/job?id=${interrupted}`)).json()).status,'interrupted'); + const retry=await fetch(base+'/synth',{method:'POST',headers:{'Content-Type':'application/json','X-Yue2-Job-Id':id},body:JSON.stringify({style:'Audit replay'})}); + assert.equal(retry.status,200);assert.equal((await retry.json()).id,id); + assert.equal((await(await fetch(base+`/job?id=${id}`)).json()).status,'done'); + assert.equal((await fetch(base+`/job?id=${id}&ack=1`,{method:'POST'})).status,200); + await stop(); + } + console.log('PASS: archived binary results survive server restart; retries return the same completed job; interrupted status and acknowledgement work. No synthesis performed.'); +}finally{await stop();} diff --git a/tests/server-smoke.mjs b/tests/server-smoke.mjs new file mode 100644 index 0000000..f1e7587 --- /dev/null +++ b/tests/server-smoke.mjs @@ -0,0 +1,51 @@ +// Read-only API checks against a temporary CPU server, never the user's live port. +import { spawn } from 'node:child_process'; +import { once } from 'node:events'; +import assert from 'node:assert/strict'; +import { fileURLToPath } from 'node:url'; + +const root = fileURLToPath(new URL('../', import.meta.url)); +const env = Object.fromEntries(Object.entries(process.env).map(([key, value]) => [key.toUpperCase(), value])); +env.GGML_BACKEND = 'CPU'; +const child = spawn(process.argv[2] || `${root}build/audit-repair/yue-server.exe`, [ + '--host', '127.0.0.1', '--port', '18087', '--max-seq', '512', + '--model', 'models/YuE2-3B-Q8_0.gguf', '--vae', 'models/YuE2-Vae-F32.gguf' +], { cwd: root, env, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] }); +let logs = ''; +child.stdout.on('data', chunk => { logs = (logs + chunk).slice(-12000); }); +child.stderr.on('data', chunk => { logs = (logs + chunk).slice(-12000); }); +let startupError; +child.on('error', error => { startupError = error; }); +const base = 'http://127.0.0.1:18087'; +try { + let ready = false; + for (let n = 0; n < 100; n++) { + if (startupError) throw startupError; + if (child.exitCode !== null) throw new Error(`Server exited: ${logs}`); + try { ready = (await fetch(`${base}/health`, { signal: AbortSignal.timeout(500) })).ok; } catch {} + if (ready) break; + await new Promise(resolve => setTimeout(resolve, 200)); + } + assert.ok(ready, `Temporary server failed to start: ${logs}`); + const props = await (await fetch(`${base}/props`)).json(); + assert.equal(props.defaults.mp3_bitrate, 320); + assert.equal(props.sample_rate, 48000); + for (const request of [{ steps: 201 }, { duration: 601 }, { duration: -2 }, { cfg_scale: 31 }, { peak_clip: 1000 }, { output_format: 'mp3', mp3_bitrate: 321 }]) { + const response = await fetch(`${base}/synth`, { method: 'POST', body: JSON.stringify(request) }); + assert.equal(response.status, 400, JSON.stringify(request)); + assert.ok((await response.json()).error); + } + const oversized = await fetch(`${base}/synth`, { method: 'POST', body: JSON.stringify({ lyrics: 'a'.repeat(1024 * 1024) }) }); + assert.equal(oversized.status, 413); + const ui = await (await fetch(`${base}/`, { headers: { 'Accept-Encoding': 'gzip' } })).text(); + assert.ok(ui.includes('Relative') || ui.includes('relative influence')); + assert.ok(ui.includes('Ollama model')); + if (process.argv[2]) assert.ok(ui.includes('Lock voice profiles across songs')); + console.log('PASS: temporary CPU server; 320 kbps/48 kHz defaults; six invalid requests; oversized request; embedded updated UI. No songs generated.'); +} finally { + if (child.exitCode === null) { + const exited = once(child, 'exit'); + child.kill(); + await exited; + } +} diff --git a/tests/studio-interactions.mjs b/tests/studio-interactions.mjs new file mode 100644 index 0000000..1e9bbb3 --- /dev/null +++ b/tests/studio-interactions.mjs @@ -0,0 +1,116 @@ +import { chromium } from '../tools/youtube-agent/node_modules/playwright/index.mjs'; +import { readFile, writeFile, mkdir } from 'node:fs/promises'; +import assert from 'node:assert/strict'; +await mkdir('build/ui-review',{recursive:true}); +const browser = await chromium.launch({...(process.env.CI ? {} : {channel:'msedge'}),headless:true}); +try { + const page = await browser.newPage({viewport:{width:1536,height:1024}}); + const errors=[]; page.on('pageerror',error=>errors.push(error.message)); + let presets=[], rejected=0; + await page.route('**/*',async route=>{ + const request=route.request(), url=new URL(request.url()); + if(url.origin==='http://localhost:8087' && url.pathname==='/') return route.fulfill({contentType:'text/html',body:await readFile('tools/webui/dist/index.html')}); + if(url.pathname==='/presets') { + if(request.method()==='POST') { + const p=request.postDataJSON(); await new Promise(resolve=>setTimeout(resolve,250)); + presets=presets.filter(x=>!(x.name===p.name && x.kind===p.kind)); + if(p.operation!=='delete') presets.push({name:p.name,kind:p.kind,data:p.data}); + } + return route.fulfill({json:presets}); + } + if(request.method()==='POST') { rejected++; await new Promise(resolve=>setTimeout(resolve,600)); return route.fulfill({status:503,json:{error:'Interaction review: simulated unavailable service'}}); } + if(url.pathname==='/jobs')return route.fulfill({json:[]}); + if(url.pathname==='/api/tags')return route.fulfill({json:{models:[]}}); + return route.fulfill({json:{status:'ok',defaults:{},sample_rate:48000,context:24576}}); + }); + await page.goto('http://localhost:8087'); + await page.getByRole('heading',{name:'Create your song'}).waitFor(); + // Seed only the disposable browser's library with a silent, valid WAV and cover. + await page.evaluate(async()=>{ + const buffer=new ArrayBuffer(44+16000*2*12), view=new DataView(buffer); + const str=(offset,s)=>[...s].forEach((c,i)=>view.setUint8(offset+i,c.charCodeAt(0))); + str(0,'RIFF');view.setUint32(4,buffer.byteLength-8,true);str(8,'WAVE');str(12,'fmt ');view.setUint32(16,16,true);view.setUint16(20,1,true);view.setUint16(22,1,true);view.setUint32(24,16000,true);view.setUint32(28,32000,true);view.setUint16(32,2,true);view.setUint16(34,16,true);str(36,'data');view.setUint32(40,buffer.byteLength-44,true); + const canvas=document.createElement('canvas');canvas.width=canvas.height=64;const ctx=canvas.getContext('2d');ctx.fillStyle='#7744cc';ctx.fillRect(0,0,64,64); + const artwork=await new Promise(resolve=>canvas.toBlob(resolve)); + const db=await new Promise((resolve,reject)=>{const r=indexedDB.open('yue2-songs');r.onupgradeneeded=()=>r.result.createObjectStore('songs',{keyPath:'id',autoIncrement:true});r.onsuccess=()=>resolve(r.result);r.onerror=()=>reject(r.error);}); + await new Promise((resolve,reject)=>{const tx=db.transaction('songs','readwrite');tx.objectStore('songs').put({id:1,name:'Interaction review track',created:1,duration:12,format:'wav',style:'Jazz Rap',seed:1,score:'',artwork,audio:new Blob([buffer],{type:'audio/wav'}),request:{style:'Jazz Rap',abc_sampling:{},semantic_sampling:{}}});tx.oncomplete=resolve;tx.onerror=()=>reject(tx.error);});db.close(); + }); + await page.reload(); + await page.getByRole('heading',{name:'Create your song'}).waitFor(); + await page.getByRole('button',{name:'Manage saved presets'}).click(); + await page.getByRole('button',{name:'Edit style blends'}).click(); + const blends=page.locator('#music-workbench .favourites'); + await blends.getByPlaceholder('Name your preset').fill('Review preset'); + await blends.getByRole('button',{name:'Save new',exact:true}).click(); + await blends.getByRole('status').waitFor(); + assert.ok(await blends.getByRole('button',{name:'Load',exact:true}).isDisabled()); + await page.getByRole('button',{name:'Load music preset Review preset'}).waitFor(); + await blends.getByRole('button',{name:'Load',exact:true}).click(); + await page.getByRole('status').filter({hasText:'Loaded preset:'}).waitFor(); + await page.getByRole('button',{name:/^Library/}).click(); + const card=page.locator('.song-list > .card').first(), trigger=card.getByRole('button',{name:'Track actions'}); + await trigger.focus(); await page.keyboard.press('ArrowDown'); + assert.equal(await page.locator(':focus').innerText(),'Edit prompt'); + await page.keyboard.press('End'); assert.equal(await page.locator(':focus').innerText(),'Delete non-favorites'); + await page.keyboard.press('Home'); assert.equal(await page.locator(':focus').innerText(),'Edit prompt'); + await page.keyboard.press('Escape'); assert.ok(await trigger.evaluate(el=>el===document.activeElement)); + await page.screenshot({path:'build/ui-review/interaction-library.png'}); + await trigger.click();await page.getByRole('menuitem',{name:'Rename song',exact:true}).click(); + const dialog=page.getByRole('dialog',{name:'Rename song'}); + await dialog.waitFor(); assert.ok(await dialog.getByLabel('Song name').evaluate(el=>el===document.activeElement)); + await page.keyboard.press('Shift+Tab'); assert.equal(await page.locator(':focus').innerText(),'OK'); + await page.keyboard.press('Tab'); assert.ok(await dialog.getByLabel('Song name').evaluate(el=>el===document.activeElement)); + await page.keyboard.press('Escape'); assert.ok(await trigger.evaluate(el=>el===document.activeElement)); + await card.getByRole('button',{name:'Favourite Interaction review track'}).click(); + await page.waitForFunction(()=>document.querySelector('button[aria-label="Favourite Interaction review track"]')?.getAttribute('aria-pressed')==='true'); + const wave=card.getByRole('slider',{name:'Seek in Interaction review track'}); + await wave.focus();await page.keyboard.press('ArrowRight');assert.equal(await wave.getAttribute('aria-valuenow'),'5'); + await page.keyboard.press('Home');assert.equal(await wave.getAttribute('aria-valuenow'),'0'); + await page.keyboard.press('Space');await page.waitForTimeout(100);assert.equal(await card.locator('.play-btn').getAttribute('aria-pressed'),'true');await page.keyboard.press('Space'); + await card.getByRole('button',{name:'Expand artwork for Interaction review track'}).click(); + await page.getByRole('dialog',{name:'Artwork for Interaction review track'}).waitFor(); + await page.keyboard.press('Escape');await page.waitForTimeout(350); + await trigger.click();await page.getByRole('menuitem',{name:'Transcribe score',exact:true}).click(); + await card.getByRole('status').filter({hasText:'Transcribing audio'}).waitFor(); + await trigger.click();assert.ok(await page.getByRole('menuitem',{name:'Transcribe melody'}).isDisabled());await page.keyboard.press('Escape'); + await page.getByRole('status').filter({hasText:'Transcription failed'}).waitFor(); + await trigger.click();await page.getByRole('menuitem',{name:'Prepare for YouTube'}).click(); + await page.getByLabel('Description',{exact:true}).fill('Line one');await page.keyboard.press('Enter');assert.equal(await page.getByRole('dialog',{name:'Prepare for YouTube'}).count(),1); + await page.getByRole('button',{name:'Save draft',exact:true}).click();await page.getByRole('status').filter({hasText:'Draft saved.'}).waitFor();await page.getByRole('button',{name:'Close',exact:true}).click(); + // Exercise library operations against the disposable fixture. + await trigger.click();await page.getByRole('menuitem',{name:'Rename song',exact:true}).click(); + await page.getByLabel('Song name').fill('Renamed review track');await page.getByRole('button',{name:'OK',exact:true}).click(); + await page.waitForFunction(()=>document.querySelector('.card-name')?.textContent==='Renamed review track'); + await trigger.click(); + const audioDownload=page.waitForEvent('download');await page.getByRole('menuitem',{name:'Download audio',exact:true}).click();await audioDownload; + const backupDownload=page.waitForEvent('download');await page.getByRole('button',{name:'Backup',exact:true}).click();const backup=await backupDownload; + page.on('dialog',dialog=>dialog.accept());await page.getByLabel('Choose a YuE2 library backup').setInputFiles(await backup.path()); + await page.waitForTimeout(1200);await page.getByRole('heading',{name:'Create your song'}).waitFor(); + const audit=[]; + // Hover and keyboard focus every visible control, including all expanded panels. + await page.getByRole('button',{name:'Create',exact:true}).click(); + await page.locator('.style-tile').first().click(); + assert.equal(await page.locator('.style-tile').first().getAttribute('aria-pressed'),'true'); + await page.getByRole('button',{name:'Manual control',exact:true}).click(); + await page.evaluate(()=>document.querySelectorAll('details').forEach(d=>d.open=true)); + const temperature=page.locator('#score-sampling').getByRole('slider',{name:'Temperature slider'}); + await temperature.focus(); await page.keyboard.press('ArrowRight'); + assert.ok(await page.locator('#score-sampling').getByRole('spinbutton',{name:'Temperature',exact:true}).inputValue()); + await page.keyboard.press('Tab'); + const controls=page.locator('button:visible, a:visible, summary:visible, input:visible, select:visible, textarea:visible, [role="slider"]:visible'); + const count=await controls.count(); + for(let i=0;i({tag:el.tagName,name:el.getAttribute('aria-label')||el.getAttribute('title')||el.textContent?.trim().slice(0,80)||el.closest('label')?.textContent?.trim().slice(0,80),disabled:el.matches(':disabled')})); + if(!item.disabled) { await c.focus(); item.focus=await c.evaluate(el=>getComputedStyle(el).outlineStyle); assert.notEqual(item.focus,'none',`Missing keyboard focus: ${item.name}`); } + audit.push(item); + } + await writeFile('build/ui-review/control-inventory.json',JSON.stringify(audit,null,2)); + await page.emulateMedia({reducedMotion:'reduce'}); + assert.equal(await page.locator('.generate-btn').evaluate(el=>getComputedStyle(el).transitionDuration),'0s'); + await page.locator('.generate-btn').hover();assert.equal(await page.locator('.generate-btn').evaluate(el=>getComputedStyle(el).transform),'none'); + await page.setViewportSize({width:390,height:844}); + assert.ok(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth),'Phone overflow'); + assert.deepEqual(errors,[]); + console.log(`PASS: ${audit.length} controls inventoried/focused; preset busy/load, menu arrows/Home/End/Escape, dialog focus/trap/restore, favourite, waveform seek/play, artwork, transcription busy/error, YouTube save, rename, audio download, backup/restore, reduced motion, phone width. ${rejected} server mutation mocked.`); +} finally {await browser.close();} diff --git a/tests/workflow-browser.mjs b/tests/workflow-browser.mjs new file mode 100644 index 0000000..fa1d96f --- /dev/null +++ b/tests/workflow-browser.mjs @@ -0,0 +1,50 @@ +import {chromium} from '../tools/youtube-agent/node_modules/playwright/index.mjs'; +import {readFile,writeFile,mkdir} from 'node:fs/promises'; +import assert from 'node:assert/strict'; +const browser=await chromium.launch({...(process.env.CI?{}:{channel:'msedge'}),headless:true}); +const html=await readFile('tools/webui/dist/index.html'); +const wav=Buffer.alloc(32044);wav.write('RIFF');wav.writeUInt32LE(wav.length-8,4);wav.write('WAVEfmt ',8);wav.writeUInt32LE(16,16);wav.writeUInt16LE(1,20);wav.writeUInt16LE(1,22);wav.writeUInt32LE(16000,24);wav.writeUInt32LE(32000,28);wav.writeUInt16LE(2,32);wav.writeUInt16LE(16,34);wav.write('data',36);wav.writeUInt32LE(32000,40); +const result=Buffer.concat([Buffer.from('--fixture\r\nContent-Type: application/json\r\n\r\n'+JSON.stringify({style:'Jazz Rap',abc_sampling:{},semantic_sampling:{}})+'\r\n--fixture\r\nContent-Type: audio/wav\r\n\r\n'),wav,Buffer.from('\r\n--fixture--\r\n')]); +try{ + const page=await browser.newPage(),errors=[],submitted=new Set();let done=false,presets=[]; + page.on('pageerror',e=>errors.push(e.message)); + await page.addInitScript(()=>{window.decodeCalls=0;const old=AudioContext.prototype.decodeAudioData;AudioContext.prototype.decodeAudioData=function(...args){window.decodeCalls++;return old.apply(this,args);};}); + await page.route('**/*',route=>{const r=route.request(),u=new URL(r.url()); + if(u.pathname==='/')return route.fulfill({contentType:'text/html',body:html}); + if(u.pathname==='/presets'){if(r.method()==='POST'){const p=r.postDataJSON();if(p.operation==='rename')presets=presets.filter(x=>x.name!==p.oldName);else presets=presets.filter(x=>x.name!==p.name);if(p.operation!=='delete')presets.push(p);}return route.fulfill({json:presets});} + if(u.pathname==='/synth'){const id=r.headers()['x-yue2-job-id'];submitted.add(id);return route.fulfill({json:{id}});} + if(u.pathname==='/job')return u.searchParams.has('result')?route.fulfill({contentType:'multipart/mixed; boundary=fixture',body:result}):route.fulfill({json:{status:done?'done':'running',durable:true}}); + if(u.pathname==='/jobs')return route.fulfill({json:[]}); + return route.fulfill({json:{status:'ok',models:[],defaults:{}}}); + }); + await page.goto('http://localhost:8087');await page.getByRole('heading',{name:'Create your song'}).waitFor(); + await page.getByRole('button',{name:'Save preset',exact:true}).click(); + await page.getByRole('dialog').getByLabel('Preset name').fill('Full setup check'); + await page.getByRole('dialog').getByRole('button',{name:'Save full preset',exact:true}).click(); + await page.getByRole('button',{name:'Load studio preset Full setup check'}).waitFor(); + assert.equal(presets[0].kind,'studio');assert.ok(presets[0].data.configuration.producer); + await page.getByRole('button',{name:'Manage saved presets'}).click(); + await page.getByRole('dialog').getByRole('button',{name:'Full setup check · Full Studio setup'}).click(); + await page.getByRole('dialog').getByLabel('Preset name').fill('Renamed full setup'); + await page.getByRole('dialog').getByRole('button',{name:'Save name'}).click(); + await page.getByRole('button',{name:'Load studio preset Renamed full setup'}).waitFor(); + await page.getByRole('dialog').getByRole('button',{name:'Close',exact:true}).click(); + await page.getByRole('button',{name:/^Library/}).click(); + await page.getByRole('link',{name:'Shape your first track'}).click();await page.getByRole('heading',{name:'Create your song'}).waitFor(); + await page.getByRole('button',{name:/^Library/}).click(); + const albums=page.locator('#albums');await albums.getByLabel('Album title').fill('Recovery test'); + await albums.getByLabel('Generate master cover').uncheck();await albums.getByLabel('Export MP4').uncheck(); + await albums.locator('input[type=file]').setInputFiles([{name:'One.txt',mimeType:'text/plain',buffer:Buffer.from('[Verse]\nOne bright morning')},{name:'Two.txt',mimeType:'text/plain',buffer:Buffer.from('[Verse]\nTwo steps forward')}]); + await albums.getByRole('button',{name:'Generate album',exact:true}).click(); + await page.waitForFunction(()=>document.querySelector('#albums')?.textContent.includes('generating audio')); + await page.waitForTimeout(500);assert.equal(submitted.size,1); + await page.reload();await page.getByRole('button',{name:/^Library/}).click();done=true; + await albums.getByRole('button',{name:'Resume album',exact:true}).click(); + await albums.getByRole('status').filter({hasText:'Album complete'}).waitFor({timeout:20000});assert.equal(submitted.size,2,'resume reuses first ID');assert.equal(await page.locator('.song-list .card').count(),2); + await page.evaluate(async bytes=>{const db=await new Promise((resolve,reject)=>{const q=indexedDB.open('yue2-songs');q.onsuccess=()=>resolve(q.result);q.onerror=()=>reject(q.error);});await new Promise((resolve,reject)=>{const tx=db.transaction('songs','readwrite');for(let i=0;i<120;i++)tx.objectStore('songs').add({name:'Stress '+i,created:i+100,format:'wav',duration:1,style:'Jazz Rap',seed:1,score:'',audio:new Blob([new Uint8Array(bytes)],{type:'audio/wav'}),peaks:[.2,.5,.3],request:{style:'Jazz Rap',abc_sampling:{},semantic_sampling:{}}});tx.oncomplete=resolve;tx.onerror=()=>reject(tx.error);});db.close();},[...wav]); + await page.reload();await page.getByRole('button',{name:/^Library/}).click();await page.waitForTimeout(1500); + assert.equal(await page.locator('.song-list .card').count(),12,'pagination bounds mounted cards');assert.equal(await page.evaluate(()=>window.decodeCalls),0,'cached peaks avoid eager audio decoding'); + const metrics=await (await page.context().newCDPSession(page)).send('Runtime.getHeapUsage');assert.deepEqual(errors,[]); + await mkdir('build/ui-review',{recursive:true});await writeFile('build/ui-review/workflows.json',JSON.stringify({tracks:122,mountedCards:12,decodeCalls:0,heap:metrics,albumResume:'passed',pageErrors:errors},null,2)); + console.log('PASS: empty-library navigation, two-track album reload/resume without duplicate submission, 122-track pagination, zero eager decoding for cached peaks.',metrics); +}finally{await browser.close();} diff --git a/tools/activate-studio.mjs b/tools/activate-studio.mjs new file mode 100644 index 0000000..b508c14 --- /dev/null +++ b/tools/activate-studio.mjs @@ -0,0 +1,8 @@ +import {spawnSync} from 'node:child_process'; +import {fileURLToPath} from 'node:url'; +if(process.platform!=='win32')throw Error('This deployment wrapper is for the Windows music launcher.'); +const root=fileURLToPath(new URL('../',import.meta.url)); +// Windows environment keys are case insensitive; inherited Path/PATH duplicates +// break PowerShell Start-Process unless normalized before starting the shell. +const env=Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v])); +const r=spawnSync('powershell.exe',['-NoProfile','-ExecutionPolicy','Bypass','-File','tools/activate-studio.ps1'],{cwd:root,env,stdio:'inherit',windowsHide:true});process.exit(r.status??1); diff --git a/tools/activate-studio.ps1 b/tools/activate-studio.ps1 new file mode 100644 index 0000000..0a4b0ce --- /dev/null +++ b/tools/activate-studio.ps1 @@ -0,0 +1,47 @@ +$ErrorActionPreference = 'Stop' +$studioRoot = Split-Path -Parent $PSScriptRoot +$candidate = Join-Path $studioRoot 'build\Release-producer' +$target = Join-Path $studioRoot 'build\Release-reference' +$executable = Join-Path $target 'yue-server.exe' +$files = @('yue-server.exe','ggml.dll','ggml-base.dll','ggml-cpu.dll','ggml-cuda.dll') +foreach ($file in $files) { + if (-not (Test-Path -LiteralPath (Join-Path $candidate $file))) { throw "Candidate missing $file" } +} +$currentServer = Get-Process yue-server -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $executable } | Select-Object -First 1 +if ($currentServer) { + Write-Output "Preparing to replace server PID $($currentServer.Id)." + try { $jobs = Invoke-RestMethod 'http://127.0.0.1:8087/jobs' -TimeoutSec 3; if ($jobs.Count -gt 0) { throw 'Wait for active jobs to finish before activation.' } } + catch { if ($_.Exception.Message -notmatch '404') { throw } } +} +$backup = Join-Path $studioRoot ('build\backup-before-producer-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) +New-Item -ItemType Directory -Path $backup | Out-Null +foreach ($file in $files) { Copy-Item -LiteralPath (Join-Path $target $file) -Destination (Join-Path $backup $file) } +$env:PATH = "$studioRoot\.venv-vocal\Scripts;$target;$studioRoot\build\Release;$env:PATH" +$serverArguments = @('--host','127.0.0.1','--port','8087','--model','models\YuE2-3B-Q8_0.gguf','--vae','models\YuE2-Vae-F32.gguf','--transcriber','models\SheetSage2-Q8_0.gguf') +$nextServer = $null +try { + if ($currentServer) { $currentServer.Kill(); if (-not $currentServer.WaitForExit(10000)) { throw 'Server did not stop within 10 seconds.' } } + foreach ($file in $files) { + for ($attempt=0; $attempt -lt 20; $attempt++) { + try { Copy-Item -LiteralPath (Join-Path $candidate $file) -Destination (Join-Path $target $file) -Force; break } + catch { if ($attempt -eq 19) { throw }; Start-Sleep -Milliseconds 250 } + } + } + $nextServer = Start-Process -FilePath $executable -ArgumentList $serverArguments -WorkingDirectory $studioRoot -WindowStyle Hidden -RedirectStandardOutput "$studioRoot\build\producer-server.out.log" -RedirectStandardError "$studioRoot\build\producer-server.err.log" -PassThru + $healthy = $false + for ($attempt = 0; $attempt -lt 40; $attempt++) { + Start-Sleep -Milliseconds 500 + $nextServer.Refresh() + if ($nextServer.HasExited) { throw 'Updated server exited during startup.' } + try { if ((Invoke-RestMethod 'http://127.0.0.1:8087/health' -TimeoutSec 2).status -eq 'ok') { $healthy = $true; break } } catch {} + } + if (-not $healthy) { throw 'Updated server did not become ready.' } + Write-Output "Producer controls active on http://localhost:8087. PID $($nextServer.Id). Previous build: $backup" +} catch { + $activationError = $_ + Write-Output "Activation failed: $activationError at $($_.ScriptStackTrace)" + if ($nextServer -and -not $nextServer.HasExited) { $nextServer.Kill(); $null = $nextServer.WaitForExit(10000) } + foreach ($file in $files) { Copy-Item -LiteralPath (Join-Path $backup $file) -Destination (Join-Path $target $file) -Force } + Start-Process -FilePath $executable -ArgumentList $serverArguments -WorkingDirectory $studioRoot -WindowStyle Hidden + throw +} diff --git a/tools/build-studio.mjs b/tools/build-studio.mjs new file mode 100644 index 0000000..7f4a9bc --- /dev/null +++ b/tools/build-studio.mjs @@ -0,0 +1,8 @@ +import {spawnSync} from 'node:child_process'; +import {fileURLToPath} from 'node:url'; +import {join} from 'node:path'; +const root=fileURLToPath(new URL('../',import.meta.url)); +const env=process.platform==='win32'?Object.fromEntries(Object.entries(process.env).map(([k,v])=>[k.toUpperCase(),v])):process.env; +const args=['--build','build','--config','Release','--target','yue-server']; +if(process.platform==='win32')args.push('--',`/p:OutDir=${join(root,'build/Release-producer/').replaceAll('\\','/')}`); +const r=spawnSync('cmake',args,{cwd:root,env,stdio:'inherit',windowsHide:true});if(r.error)console.error(r.error);process.exit(r.status??1); diff --git a/tools/comfy-api.h b/tools/comfy-api.h new file mode 100644 index 0000000..86a499b --- /dev/null +++ b/tools/comfy-api.h @@ -0,0 +1,30 @@ +#pragma once +#include "httplib.h" +#include +#include + +// Narrow loopback-only bridge: no arbitrary destinations or manager endpoints. +static void register_comfy_api(httplib::Server & server, int port, std::function busy = {}, std::timed_mutex * gate = nullptr) { + auto forward = [port,busy,gate](const httplib::Request & req, httplib::Response & res) { + std::unique_lock ownership; + if(req.target=="/comfy/prompt" && gate) {ownership=std::unique_lock(*gate,std::try_to_lock);if(!ownership.owns_lock()){res.status=409;res.set_content("Studio is using the GPU; retry when it finishes.","text/plain");return;}} + if(req.target=="/comfy/prompt" && busy && busy()) {res.status=409;res.set_content("Studio is using the GPU. Wait for the current operation to finish.","text/plain");return;} + if (req.body.size() > 24 * 1024 * 1024) { res.status = 413; res.set_content("Artwork request too large", "text/plain"); return; } + httplib::Client client("127.0.0.1", port); + client.set_connection_timeout(3); + client.set_read_timeout(30); + client.set_write_timeout(30); + const std::string target = req.target.substr(6); + httplib::UploadFormDataItems items; + size_t size=req.body.size(); + for(const auto &entry:req.form.fields){const auto &v=entry.second;items.push_back({v.name,v.content,"",""});size+=v.content.size();} + for(const auto &entry:req.form.files){const auto &v=entry.second;items.push_back({v.name,v.content,v.filename,v.content_type});size+=v.content.size();} + if(size>24*1024*1024){res.status=413;return;} + auto result = req.method == "GET" ? client.Get(target) : req.is_multipart_form_data() ? client.Post(target,items) : client.Post(target, req.body, req.get_header_value("Content-Type")); + if (!result) { res.status = 503; res.set_content("ComfyUI is unavailable. Start the configured ComfyUI app and check artwork readiness.", "text/plain"); return; } + res.status = result->status; + res.set_content(result->body, result->get_header_value("Content-Type")); + }; + server.Get(R"(/comfy/(object_info|queue|history/[a-zA-Z0-9-]+|view))", forward); + server.Post(R"(/comfy/(prompt|upload/image|free))", forward); +} diff --git a/tools/mp3-codec.cpp b/tools/mp3-codec.cpp index 2d2d709..f8a6fe9 100644 --- a/tools/mp3-codec.cpp +++ b/tools/mp3-codec.cpp @@ -63,7 +63,7 @@ int main(int argc, char ** argv) { const char * input = NULL; const char * output = NULL; - int bitrate = 128; + int bitrate = 320; WavFormat wav_fmt = WAV_S16; for (int i = 1; i < argc; i++) { diff --git a/tools/public/index.html.gz b/tools/public/index.html.gz index 4ce34e4..62d7f1d 100644 Binary files a/tools/public/index.html.gz and b/tools/public/index.html.gz differ diff --git a/tools/repair-comfy-gguf.mjs b/tools/repair-comfy-gguf.mjs new file mode 100644 index 0000000..4f14107 --- /dev/null +++ b/tools/repair-comfy-gguf.mjs @@ -0,0 +1,21 @@ +// Narrow compatibility repair for metadata-free Qwen Image 2.1 GGUF exports. +// Supply the installed GGUF node directory; no model download or launcher edits. +import {readFile,writeFile,copyFile,access} from 'node:fs/promises'; +import {resolve,join} from 'node:path'; +const folder=resolve(process.argv[2]??''),file=join(folder,'tools/convert.py'); +const source=await readFile(file,'utf8'); +if(source.includes('class ModelQwenImage21')){console.log('Qwen Image 2.1 detector already present.');process.exit(0);} +if(!source.includes('ModelKrea2, ModelIdeogram, ModelMinimaxH3]')||!source.includes('arch_list = ['))throw Error('Loader changed; review the patch before applying.'); +const block=`class ModelQwenImage21(ModelTemplate): + arch = "qwen_image" + keys_detect = [( + "txt_in.text_norm.weight", "modulation.1.weight", + "transformer_blocks.0.attn.norm_q.weight", "img_in.weight", + "proj_out.weight", "transformer_blocks.0.img_mlp.proj.weight", + )] + + +`; +const target=source.replace('arch_list = [',block+'arch_list = [').replace('ModelKrea2, ModelIdeogram, ModelMinimaxH3]','ModelKrea2, ModelIdeogram, ModelMinimaxH3, ModelQwenImage21]'); +const backup=file+'.before-yue2-qwen21';try{await access(backup);throw Error('Repair backup already exists; inspect it before replacing anything.');}catch(error){if(error.code!=='ENOENT')throw error;} +await copyFile(file,backup);await writeFile(file,target,'utf8');console.log('Added Qwen Image 2.1 tensor signature; original saved at '+backup); diff --git a/tools/webui/index.html b/tools/webui/index.html index f4ecfa9..a70fe35 100644 --- a/tools/webui/index.html +++ b/tools/webui/index.html @@ -3,7 +3,8 @@ - yue2.cpp - AI Music Generator + YuE2 Studio - AI Music Generator +
diff --git a/tools/webui/package-lock.json b/tools/webui/package-lock.json index fd8dc4c..8ad905e 100644 --- a/tools/webui/package-lock.json +++ b/tools/webui/package-lock.json @@ -23,9 +23,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -39,9 +39,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -55,9 +55,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -71,9 +71,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -87,9 +87,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -103,9 +103,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -119,9 +119,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -135,9 +135,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -151,9 +151,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -167,9 +167,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -183,9 +183,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -199,9 +199,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -215,9 +215,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -231,9 +231,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -247,9 +247,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -263,9 +263,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -279,9 +279,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -295,9 +295,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -311,9 +311,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -327,9 +327,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -343,9 +343,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -359,9 +359,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -375,9 +375,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -391,9 +391,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -407,9 +407,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -423,9 +423,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -468,9 +468,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -857,9 +857,9 @@ ] }, "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz", - "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.13.tgz", + "integrity": "sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==", "license": "MIT", "peerDependencies": { "acorn": "^8.9.0" @@ -910,29 +910,10 @@ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/types": { - "version": "8.58.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz", - "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1007,15 +988,15 @@ } }, "node_modules/devalue": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz", - "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==", + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.4.tgz", + "integrity": "sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==", "license": "MIT" }, "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -1025,32 +1006,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/esm-env": { @@ -1060,13 +1041,20 @@ "license": "MIT" }, "node_modules/esrap": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz", - "integrity": "sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.4.0.tgz", + "integrity": "sha512-CQPcneEHw/czj32uwQC52nYnax8H4SXt25FCM+LIwGZ49cMIxpOj3bP8wmzcI+Z0HIy5KkClaPhRLfCySzwHPA==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15", + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "peerDependencies": { "@typescript-eslint/types": "^8.2.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/types": { + "optional": true + } } }, "node_modules/fdir": { @@ -1181,9 +1169,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", "funding": [ { "type": "github", @@ -1228,9 +1216,9 @@ } }, "node_modules/postcss": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", - "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -1247,7 +1235,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -1363,23 +1351,22 @@ } }, "node_modules/svelte": { - "version": "5.55.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.2.tgz", - "integrity": "sha512-z41M/hi0ZPTzrwVKLvB/R1/Oo08gL1uIib8HZ+FncqxxtY9MLb01emg2fqk+WLZ/lNrrtNDFh7BZLDxAHvMgLw==", + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.57.1.tgz", + "integrity": "sha512-Uqj49lWKB+iSSnneuwiYYJ7MZgkB+eXr0LXBhv4uDuAkXqnWmq65Sxflfvp0Lc6MdKjMUxGaeOKWJqz5SNiVIA==", "license": "MIT", "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "@jridgewell/sourcemap-codec": "^1.5.0", - "@sveltejs/acorn-typescript": "^1.0.5", - "@types/estree": "^1.0.5", - "@types/trusted-types": "^2.0.7", - "acorn": "^8.12.1", + "@jridgewell/remapping": "^2.3.5", + "@jridgewell/sourcemap-codec": "^1.6.0", + "@sveltejs/acorn-typescript": "^1.0.13", + "@types/estree": "^1.0.9", + "acorn": "^8.18.0", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", - "devalue": "^5.6.4", + "devalue": "^5.9.2", "esm-env": "^1.2.1", - "esrap": "^2.2.4", + "esrap": "^2.3.6", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -1413,6 +1400,12 @@ "typescript": ">=5.0.0" } }, + "node_modules/svelte/node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -1456,12 +1449,12 @@ } }, "node_modules/vite": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", - "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", diff --git a/tools/webui/src/App.svelte b/tools/webui/src/App.svelte index b1036e2..2cb7d48 100644 --- a/tools/webui/src/App.svelte +++ b/tools/webui/src/App.svelte @@ -1,18 +1,51 @@
-
- yue2.cpp - {__YUE2_VERSION__} -
- -
- - + {#if app.storageWarning}
{app.storageWarning}
{/if} +
+
YuE2 StudioLOCAL STUDIO
+
+ {#if app.props}{:else}{/if}{statusText}⌄
+
+
+ + focusSection('settings')} aria-label="Studio settings">
-
-
- -
-
- -
-
+
+ + +
+
+ {#if currentPage === 'create'} currentPage = 'library'} />{/if} +
+ {#if currentPage === 'library'} +
+
+

Library

{app.songs.length} track{app.songs.length === 1 ? '' : 's'} saved on this device

+ + +
+
currentPage = 'library'} showGenerated={false} />
+
+ {/if} +
diff --git a/tools/webui/src/assets/style-thumbnails/001_boom_bap.webp b/tools/webui/src/assets/style-thumbnails/001_boom_bap.webp new file mode 100644 index 0000000..19dac7e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/001_boom_bap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/002_golden_era_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/002_golden_era_hip_hop.webp new file mode 100644 index 0000000..0df0fcf Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/002_golden_era_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/003_underground_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/003_underground_hip_hop.webp new file mode 100644 index 0000000..586c9e6 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/003_underground_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/004_lo_fi_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/004_lo_fi_hip_hop.webp new file mode 100644 index 0000000..fc5b604 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/004_lo_fi_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/005_jazz_rap.webp b/tools/webui/src/assets/style-thumbnails/005_jazz_rap.webp new file mode 100644 index 0000000..571cc04 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/005_jazz_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/006_conscious_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/006_conscious_hip_hop.webp new file mode 100644 index 0000000..0c2db66 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/006_conscious_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/007_abstract_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/007_abstract_hip_hop.webp new file mode 100644 index 0000000..e8f0e71 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/007_abstract_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/008_alternative_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/008_alternative_hip_hop.webp new file mode 100644 index 0000000..39fa83e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/008_alternative_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/009_backpack_rap.webp b/tools/webui/src/assets/style-thumbnails/009_backpack_rap.webp new file mode 100644 index 0000000..7cedde4 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/009_backpack_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/010_hardcore_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/010_hardcore_hip_hop.webp new file mode 100644 index 0000000..4f9c83b Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/010_hardcore_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/011_gangsta_rap.webp b/tools/webui/src/assets/style-thumbnails/011_gangsta_rap.webp new file mode 100644 index 0000000..7fdf341 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/011_gangsta_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/012_g_funk.webp b/tools/webui/src/assets/style-thumbnails/012_g_funk.webp new file mode 100644 index 0000000..7bf805a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/012_g_funk.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/013_west_coast_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/013_west_coast_hip_hop.webp new file mode 100644 index 0000000..7ca11ef Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/013_west_coast_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/014_east_coast_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/014_east_coast_hip_hop.webp new file mode 100644 index 0000000..7d71ffa Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/014_east_coast_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/015_southern_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/015_southern_hip_hop.webp new file mode 100644 index 0000000..40077c6 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/015_southern_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/016_dirty_south.webp b/tools/webui/src/assets/style-thumbnails/016_dirty_south.webp new file mode 100644 index 0000000..dded220 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/016_dirty_south.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/017_memphis_rap.webp b/tools/webui/src/assets/style-thumbnails/017_memphis_rap.webp new file mode 100644 index 0000000..ff07fb6 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/017_memphis_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/018_houston_rap.webp b/tools/webui/src/assets/style-thumbnails/018_houston_rap.webp new file mode 100644 index 0000000..f00b456 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/018_houston_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/019_chopped_and_screwed.webp b/tools/webui/src/assets/style-thumbnails/019_chopped_and_screwed.webp new file mode 100644 index 0000000..ad29aaa Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/019_chopped_and_screwed.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/020_crunk.webp b/tools/webui/src/assets/style-thumbnails/020_crunk.webp new file mode 100644 index 0000000..aba6d1e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/020_crunk.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/021_bounce.webp b/tools/webui/src/assets/style-thumbnails/021_bounce.webp new file mode 100644 index 0000000..53d3d0b Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/021_bounce.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/022_trap.webp b/tools/webui/src/assets/style-thumbnails/022_trap.webp new file mode 100644 index 0000000..70a3115 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/022_trap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/023_dark_trap.webp b/tools/webui/src/assets/style-thumbnails/023_dark_trap.webp new file mode 100644 index 0000000..6b57d6d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/023_dark_trap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/024_melodic_trap.webp b/tools/webui/src/assets/style-thumbnails/024_melodic_trap.webp new file mode 100644 index 0000000..3064e00 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/024_melodic_trap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/025_street_trap.webp b/tools/webui/src/assets/style-thumbnails/025_street_trap.webp new file mode 100644 index 0000000..eda4667 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/025_street_trap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/026_cloud_rap.webp b/tools/webui/src/assets/style-thumbnails/026_cloud_rap.webp new file mode 100644 index 0000000..3a4b9d2 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/026_cloud_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/027_plugg.webp b/tools/webui/src/assets/style-thumbnails/027_plugg.webp new file mode 100644 index 0000000..3bcb0ce Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/027_plugg.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/028_pluggnb.webp b/tools/webui/src/assets/style-thumbnails/028_pluggnb.webp new file mode 100644 index 0000000..49d25f9 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/028_pluggnb.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/029_rage.webp b/tools/webui/src/assets/style-thumbnails/029_rage.webp new file mode 100644 index 0000000..a2980ed Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/029_rage.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/030_drill.webp b/tools/webui/src/assets/style-thumbnails/030_drill.webp new file mode 100644 index 0000000..76b750a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/030_drill.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/031_chicago_drill.webp b/tools/webui/src/assets/style-thumbnails/031_chicago_drill.webp new file mode 100644 index 0000000..a2b8309 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/031_chicago_drill.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/032_uk_drill.webp b/tools/webui/src/assets/style-thumbnails/032_uk_drill.webp new file mode 100644 index 0000000..669a36f Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/032_uk_drill.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/033_brooklyn_drill.webp b/tools/webui/src/assets/style-thumbnails/033_brooklyn_drill.webp new file mode 100644 index 0000000..a110f81 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/033_brooklyn_drill.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/034_jersey_club_rap.webp b/tools/webui/src/assets/style-thumbnails/034_jersey_club_rap.webp new file mode 100644 index 0000000..653b9af Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/034_jersey_club_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/035_phonk.webp b/tools/webui/src/assets/style-thumbnails/035_phonk.webp new file mode 100644 index 0000000..219adbf Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/035_phonk.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/036_drift_phonk.webp b/tools/webui/src/assets/style-thumbnails/036_drift_phonk.webp new file mode 100644 index 0000000..4e2c47f Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/036_drift_phonk.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/037_horrorcore.webp b/tools/webui/src/assets/style-thumbnails/037_horrorcore.webp new file mode 100644 index 0000000..240c69e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/037_horrorcore.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/038_industrial_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/038_industrial_hip_hop.webp new file mode 100644 index 0000000..ee21c08 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/038_industrial_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/039_experimental_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/039_experimental_hip_hop.webp new file mode 100644 index 0000000..95f039c Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/039_experimental_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/040_glitch_hop.webp b/tools/webui/src/assets/style-thumbnails/040_glitch_hop.webp new file mode 100644 index 0000000..fe0a4a0 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/040_glitch_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/041_electronic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/041_electronic_hip_hop.webp new file mode 100644 index 0000000..172662d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/041_electronic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/042_psychedelic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/042_psychedelic_hip_hop.webp new file mode 100644 index 0000000..cd1de86 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/042_psychedelic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/043_neo_psychedelic_rap.webp b/tools/webui/src/assets/style-thumbnails/043_neo_psychedelic_rap.webp new file mode 100644 index 0000000..42861e9 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/043_neo_psychedelic_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/044_trip_hop.webp b/tools/webui/src/assets/style-thumbnails/044_trip_hop.webp new file mode 100644 index 0000000..3ad9c4d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/044_trip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/045_downtempo_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/045_downtempo_hip_hop.webp new file mode 100644 index 0000000..495a08b Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/045_downtempo_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/046_instrumental_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/046_instrumental_hip_hop.webp new file mode 100644 index 0000000..63908d3 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/046_instrumental_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/047_sampledelic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/047_sampledelic_hip_hop.webp new file mode 100644 index 0000000..ee5eac8 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/047_sampledelic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/048_soul_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/048_soul_hip_hop.webp new file mode 100644 index 0000000..b44b8b2 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/048_soul_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/049_chipmunk_soul.webp b/tools/webui/src/assets/style-thumbnails/049_chipmunk_soul.webp new file mode 100644 index 0000000..99f9e1b Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/049_chipmunk_soul.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/050_gospel_rap.webp b/tools/webui/src/assets/style-thumbnails/050_gospel_rap.webp new file mode 100644 index 0000000..258963d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/050_gospel_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/051_funk_rap.webp b/tools/webui/src/assets/style-thumbnails/051_funk_rap.webp new file mode 100644 index 0000000..d9defaa Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/051_funk_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/052_disco_rap.webp b/tools/webui/src/assets/style-thumbnails/052_disco_rap.webp new file mode 100644 index 0000000..b6054de Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/052_disco_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/053_randb_rap.webp b/tools/webui/src/assets/style-thumbnails/053_randb_rap.webp new file mode 100644 index 0000000..5d73a93 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/053_randb_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/054_neo_soul_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/054_neo_soul_hip_hop.webp new file mode 100644 index 0000000..a1bd01d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/054_neo_soul_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/055_pop_rap.webp b/tools/webui/src/assets/style-thumbnails/055_pop_rap.webp new file mode 100644 index 0000000..fc0ee7d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/055_pop_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/056_party_rap.webp b/tools/webui/src/assets/style-thumbnails/056_party_rap.webp new file mode 100644 index 0000000..d8d85c5 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/056_party_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/057_club_rap.webp b/tools/webui/src/assets/style-thumbnails/057_club_rap.webp new file mode 100644 index 0000000..7b6d18a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/057_club_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/058_miami_bass.webp b/tools/webui/src/assets/style-thumbnails/058_miami_bass.webp new file mode 100644 index 0000000..0eb9994 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/058_miami_bass.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/059_electro_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/059_electro_hip_hop.webp new file mode 100644 index 0000000..e143b16 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/059_electro_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/060_old_school_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/060_old_school_hip_hop.webp new file mode 100644 index 0000000..538b75d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/060_old_school_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/061_breakbeat_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/061_breakbeat_hip_hop.webp new file mode 100644 index 0000000..69aad4f Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/061_breakbeat_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/062_freestyle_rap.webp b/tools/webui/src/assets/style-thumbnails/062_freestyle_rap.webp new file mode 100644 index 0000000..c527d10 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/062_freestyle_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/063_battle_rap.webp b/tools/webui/src/assets/style-thumbnails/063_battle_rap.webp new file mode 100644 index 0000000..e2200d2 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/063_battle_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/064_cypher_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/064_cypher_hip_hop.webp new file mode 100644 index 0000000..0a52bb7 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/064_cypher_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/065_storytelling_rap.webp b/tools/webui/src/assets/style-thumbnails/065_storytelling_rap.webp new file mode 100644 index 0000000..2226b6e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/065_storytelling_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/066_lyrical_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/066_lyrical_hip_hop.webp new file mode 100644 index 0000000..9ae4606 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/066_lyrical_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/067_technical_rap.webp b/tools/webui/src/assets/style-thumbnails/067_technical_rap.webp new file mode 100644 index 0000000..c36a3df Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/067_technical_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/068_fast_rap_chopper.webp b/tools/webui/src/assets/style-thumbnails/068_fast_rap_chopper.webp new file mode 100644 index 0000000..8883c09 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/068_fast_rap_chopper.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/069_syllable_dense_rap.webp b/tools/webui/src/assets/style-thumbnails/069_syllable_dense_rap.webp new file mode 100644 index 0000000..ac7ef90 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/069_syllable_dense_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/070_spoken_word_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/070_spoken_word_hip_hop.webp new file mode 100644 index 0000000..9df942c Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/070_spoken_word_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/071_emo_rap.webp b/tools/webui/src/assets/style-thumbnails/071_emo_rap.webp new file mode 100644 index 0000000..59be4fd Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/071_emo_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/072_sad_rap.webp b/tools/webui/src/assets/style-thumbnails/072_sad_rap.webp new file mode 100644 index 0000000..1f0d68a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/072_sad_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/073_bedroom_rap.webp b/tools/webui/src/assets/style-thumbnails/073_bedroom_rap.webp new file mode 100644 index 0000000..9c2bd19 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/073_bedroom_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/074_indie_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/074_indie_hip_hop.webp new file mode 100644 index 0000000..92662c3 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/074_indie_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/075_lo_fi_underground.webp b/tools/webui/src/assets/style-thumbnails/075_lo_fi_underground.webp new file mode 100644 index 0000000..d46311a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/075_lo_fi_underground.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/076_grimy_boom_bap.webp b/tools/webui/src/assets/style-thumbnails/076_grimy_boom_bap.webp new file mode 100644 index 0000000..766497e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/076_grimy_boom_bap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/077_dark_boom_bap.webp b/tools/webui/src/assets/style-thumbnails/077_dark_boom_bap.webp new file mode 100644 index 0000000..e8344d2 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/077_dark_boom_bap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/078_jazz_boom_bap.webp b/tools/webui/src/assets/style-thumbnails/078_jazz_boom_bap.webp new file mode 100644 index 0000000..844c91e Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/078_jazz_boom_bap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/079_soulful_boom_bap.webp b/tools/webui/src/assets/style-thumbnails/079_soulful_boom_bap.webp new file mode 100644 index 0000000..9184f23 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/079_soulful_boom_bap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/080_cinematic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/080_cinematic_hip_hop.webp new file mode 100644 index 0000000..55cc64c Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/080_cinematic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/081_orchestral_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/081_orchestral_hip_hop.webp new file mode 100644 index 0000000..b310a8a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/081_orchestral_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/082_epic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/082_epic_hip_hop.webp new file mode 100644 index 0000000..a5ae15a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/082_epic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/083_minimal_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/083_minimal_hip_hop.webp new file mode 100644 index 0000000..defc7a4 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/083_minimal_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/084_bass_heavy_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/084_bass_heavy_hip_hop.webp new file mode 100644 index 0000000..3d5966d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/084_bass_heavy_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/085_atmospheric_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/085_atmospheric_hip_hop.webp new file mode 100644 index 0000000..0cdde1d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/085_atmospheric_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/086_dream_rap.webp b/tools/webui/src/assets/style-thumbnails/086_dream_rap.webp new file mode 100644 index 0000000..b2d7b2b Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/086_dream_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/087_space_rap.webp b/tools/webui/src/assets/style-thumbnails/087_space_rap.webp new file mode 100644 index 0000000..3eaa7c4 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/087_space_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/088_futuristic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/088_futuristic_hip_hop.webp new file mode 100644 index 0000000..6cc3adb Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/088_futuristic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/089_cyberpunk_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/089_cyberpunk_hip_hop.webp new file mode 100644 index 0000000..5d5f00d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/089_cyberpunk_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/090_retro_futuristic_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/090_retro_futuristic_hip_hop.webp new file mode 100644 index 0000000..9fc48ec Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/090_retro_futuristic_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/091_synthwave_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/091_synthwave_hip_hop.webp new file mode 100644 index 0000000..fa1e0e4 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/091_synthwave_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/092_latin_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/092_latin_hip_hop.webp new file mode 100644 index 0000000..2162a63 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/092_latin_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/093_reggae_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/093_reggae_hip_hop.webp new file mode 100644 index 0000000..d378006 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/093_reggae_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/094_dancehall_rap.webp b/tools/webui/src/assets/style-thumbnails/094_dancehall_rap.webp new file mode 100644 index 0000000..ae8bd00 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/094_dancehall_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/095_afro_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/095_afro_hip_hop.webp new file mode 100644 index 0000000..8b13fe2 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/095_afro_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/096_afrobeats_rap.webp b/tools/webui/src/assets/style-thumbnails/096_afrobeats_rap.webp new file mode 100644 index 0000000..0c37cd3 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/096_afrobeats_rap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/097_grime.webp b/tools/webui/src/assets/style-thumbnails/097_grime.webp new file mode 100644 index 0000000..31b8a20 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/097_grime.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/098_uk_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/098_uk_hip_hop.webp new file mode 100644 index 0000000..38b2da3 Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/098_uk_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/099_french_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/099_french_hip_hop.webp new file mode 100644 index 0000000..05c9d8a Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/099_french_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/100_japanese_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/100_japanese_hip_hop.webp new file mode 100644 index 0000000..fd8e20f Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/100_japanese_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/101_korean_hip_hop.webp b/tools/webui/src/assets/style-thumbnails/101_korean_hip_hop.webp new file mode 100644 index 0000000..7c7fafe Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/101_korean_hip_hop.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/102_latin_trap.webp b/tools/webui/src/assets/style-thumbnails/102_latin_trap.webp new file mode 100644 index 0000000..e0690ef Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/102_latin_trap.webp differ diff --git a/tools/webui/src/assets/style-thumbnails/103_trap_soul.webp b/tools/webui/src/assets/style-thumbnails/103_trap_soul.webp new file mode 100644 index 0000000..993f70d Binary files /dev/null and b/tools/webui/src/assets/style-thumbnails/103_trap_soul.webp differ diff --git a/tools/webui/src/components/Albums.svelte b/tools/webui/src/components/Albums.svelte new file mode 100644 index 0000000..aab277b --- /dev/null +++ b/tools/webui/src/components/Albums.svelte @@ -0,0 +1,44 @@ + +
+

Albums

Import one lyric file per track. Uses the current sound and voice plan. Audio is saved as MP3. Progress is saved after every stage.

+ + + + + + {#if busy}{/if} + {#each albums as album (album.id)}

{album.title}

{album.stage} · {album.tracks.filter(t=>t.songId).length}/{album.tracks.length} audio tracks saved

{#if album.error}

{album.error}

{/if} + +
    {#each album.tracks as track,index}
  1. {track.title} · {track.songId?'Audio saved':'Audio pending'}{album.artwork||album.video?` · Artwork ${track.artDone?'saved':'pending'}`:''}{album.video?` · Video ${track.videoDone?'saved':'pending'}`:''} + {#if album.error}{/if}
  2. {/each}
{/each} +
+ diff --git a/tools/webui/src/components/ArtworkCover.svelte b/tools/webui/src/components/ArtworkCover.svelte new file mode 100644 index 0000000..36c2c55 --- /dev/null +++ b/tools/webui/src/components/ArtworkCover.svelte @@ -0,0 +1,112 @@ + + + + + { event.preventDefault(); void close(); }} onclose={didClose} onclick={(event) => { if (event.target === dialog) void close(); }}> +
+
TRACK ARTWORK

{title}

+ {#if url}{/if} + +
+
+ + diff --git a/tools/webui/src/components/BlendFavourites.svelte b/tools/webui/src/components/BlendFavourites.svelte new file mode 100644 index 0000000..5185974 --- /dev/null +++ b/tools/webui/src/components/BlendFavourites.svelte @@ -0,0 +1,105 @@ + + +
+ Saved {kind} blends · {entries.length} +
+ + + + + + + +
+ {#if saving}

Saving preset changes…

{/if} +
+ + diff --git a/tools/webui/src/components/Dialog.svelte b/tools/webui/src/components/Dialog.svelte index a44301e..02baeca 100644 --- a/tools/webui/src/components/Dialog.svelte +++ b/tools/webui/src/components/Dialog.svelte @@ -1,5 +1,5 @@ {#if open}
-
-
{title}
+
@@ -72,34 +87,52 @@ .dialog-overlay { position: fixed; inset: 0; - background: rgba(0, 0, 0, 0.5); + background: rgba(4, 5, 8, 0.66); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); display: flex; align-items: center; justify-content: center; z-index: 100; + animation: overlay-in 0.15s ease-out; } .dialog { - background: var(--bg-card); - border-radius: 4px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); - padding: 0.75rem; - min-width: 16rem; - max-width: min(90vw, 28rem); + background: var(--bg-card-2); + border: 1px solid var(--border-strong); + border-radius: 14px; + box-shadow: var(--shadow); + padding: 1.1rem; + min-width: 17rem; + max-width: min(92vw, 28rem); display: flex; flex-direction: column; - gap: 0.5rem; + gap: 0.7rem; + animation: dialog-in 0.18s ease-out; } .dialog-title { - font-size: 0.85rem; + font-size: 0.92rem; + font-weight: 700; color: var(--fg); } .dialog-body { - font-size: 0.8rem; - color: var(--fg); + font-size: 0.83rem; + line-height: 1.55; + color: var(--fg-dim); } .dialog-footer { display: flex; justify-content: flex-end; - gap: 0.4rem; + gap: 0.5rem; + } + @keyframes overlay-in { + from { + opacity: 0; + } + } + @keyframes dialog-in { + from { + opacity: 0; + transform: translateY(0.6rem) scale(0.98); + } } diff --git a/tools/webui/src/components/DialogButton.svelte b/tools/webui/src/components/DialogButton.svelte index 8ecc86a..8e8bcd1 100644 --- a/tools/webui/src/components/DialogButton.svelte +++ b/tools/webui/src/components/DialogButton.svelte @@ -3,26 +3,42 @@ let { onclick, - children + children, + primary = false }: { onclick: (e: MouseEvent) => void; children: Snippet; + primary?: boolean; } = $props(); - + diff --git a/tools/webui/src/components/InfluenceRing.svelte b/tools/webui/src/components/InfluenceRing.svelte new file mode 100644 index 0000000..26e6cd1 --- /dev/null +++ b/tools/webui/src/components/InfluenceRing.svelte @@ -0,0 +1,34 @@ + + +
{ dragging = true; event.currentTarget.setPointerCapture(event.pointerId); move(event); }} + onpointermove={move} onpointerup={() => { dragging = false; }} onpointercancel={() => { dragging = false; }} onlostpointercapture={() => { dragging = false; }} onkeydown={key}> + {value}% +
+ + + diff --git a/tools/webui/src/components/LogCard.svelte b/tools/webui/src/components/LogCard.svelte index d467974..1fd6f2c 100644 --- a/tools/webui/src/components/LogCard.svelte +++ b/tools/webui/src/components/LogCard.svelte @@ -1,9 +1,11 @@
- +
+
{connected ? activity.stage : 'Reconnecting…'}{activity.running && connected && activity.percent !== null ? `${Math.floor(activity.percent)}%` : activity.running ? 'Working' : 'Idle'}
+ {#if activity.running && connected && activity.percent === null}{:else}{/if} +
{connected ? activity.detail || 'Start a track to see its progress' : 'Waiting for the server connection'}{activity.running && connected && activity.eta !== null ? `Stage ETA ≈ ${Math.floor(Math.ceil(activity.eta) / 60)}:${String(Math.ceil(activity.eta) % 60).padStart(2, '0')}` : activity.running ? 'ETA: unavailable' : 'ETA: —'}
+
{#if app.logsOpen} -
{lines.join('\n')}
+
ComposeRenderAudioCompleteError
+ +
{#each lines as line}
{line}
{/each}
{/if}
diff --git a/tools/webui/src/components/Menu.svelte b/tools/webui/src/components/Menu.svelte index 81921a8..0ce3f67 100644 --- a/tools/webui/src/components/Menu.svelte +++ b/tools/webui/src/components/Menu.svelte @@ -14,7 +14,7 @@