146 lines
5.9 KiB
Swift
146 lines
5.9 KiB
Swift
import MusicAssistantCore
|
|
import XCTest
|
|
|
|
final class SongProjectPromptCompilerTests: XCTestCase {
|
|
func testCompilerUsesSelectedInstrumentsInSunoStylePrompt() throws {
|
|
let project = SongProject(
|
|
title: "Compiled Song",
|
|
idea: "Prepare Suno output",
|
|
genres: [
|
|
GenreStyle(id: "arabic-pop", name: "Arabic Pop"),
|
|
GenreStyle(id: "cinematic", name: "Cinematic")
|
|
],
|
|
moods: [MoodTag(id: "hopeful", name: "Hopeful")],
|
|
bpm: ManualAutoValue(mode: .manual, value: 96),
|
|
maqam: ManualAutoValue(mode: .manual, value: "Hijaz"),
|
|
sections: [
|
|
SongSection(id: "chorus", type: .chorus, title: "Chorus", lyrics: "Section chorus")
|
|
],
|
|
instruments: [
|
|
InstrumentTrack(
|
|
instrumentId: "oud",
|
|
selected: true,
|
|
variant: "Arabic Oud",
|
|
playingStyle: "picked",
|
|
role: "main hook",
|
|
placements: [InstrumentPlacement(sectionId: "chorus", direction: "answer the vocal")]
|
|
),
|
|
InstrumentTrack(
|
|
instrumentId: "drum-kit",
|
|
selected: false,
|
|
variant: "Drum Kit"
|
|
)
|
|
],
|
|
vocalists: [Vocalist(id: "lead", label: "Lead", voiceType: "warm tenor")],
|
|
lyrics: Lyrics(text: "Approved lyrics"),
|
|
productionDirections: [ProductionDirection(id: "lift", text: "wide chorus lift")]
|
|
)
|
|
|
|
let output = try SongProjectPromptCompiler().compile(project: project)
|
|
|
|
XCTAssertEqual(output.lyricsText, "Approved lyrics")
|
|
XCTAssertTrue(output.stylePrompt.contains("Arabic Pop + Cinematic"))
|
|
XCTAssertTrue(output.stylePrompt.contains("Arabic Oud (main hook, picked, Chorus answer the vocal)"))
|
|
XCTAssertTrue(output.stylePrompt.contains("Lead warm tenor"))
|
|
XCTAssertTrue(output.stylePrompt.contains("96 BPM"))
|
|
XCTAssertTrue(output.stylePrompt.contains("maqam Hijaz"))
|
|
XCTAssertTrue(output.stylePrompt.contains("wide chorus lift"))
|
|
XCTAssertFalse(output.stylePrompt.contains("Drum Kit"))
|
|
}
|
|
|
|
func testCompilerFallsBackToOrderedSectionLyrics() throws {
|
|
let project = SongProject(
|
|
title: "Section Lyrics",
|
|
idea: "Compile sections",
|
|
sections: [
|
|
SongSection(id: "chorus", type: .chorus, title: "Chorus", order: 1, lyrics: "Hook line"),
|
|
SongSection(id: "verse", type: .verse, title: "Verse", order: 0, lyrics: "Verse line")
|
|
]
|
|
)
|
|
|
|
let output = try SongProjectPromptCompiler().compile(project: project)
|
|
|
|
XCTAssertEqual(output.lyricsText, "[Verse]\nVerse line\n\n[Chorus]\nHook line")
|
|
}
|
|
|
|
func testCompilerIncludesSectionPerformanceDirectivesInFallbackLyrics() throws {
|
|
let project = SongProject(
|
|
title: "Directed Sections",
|
|
idea: "Compile performance directions",
|
|
sections: [
|
|
SongSection(
|
|
id: "intro",
|
|
type: .intro,
|
|
title: "Intro",
|
|
lyrics: "First line",
|
|
vocalDirection: "whispered lead"
|
|
),
|
|
SongSection(
|
|
id: "chorus",
|
|
type: .chorus,
|
|
title: "Chorus",
|
|
order: 1,
|
|
lyrics: "Original hook"
|
|
)
|
|
],
|
|
lyrics: Lyrics(sectionTexts: ["chorus": "Approved hook"])
|
|
)
|
|
|
|
let output = try SongProjectPromptCompiler().compile(project: project)
|
|
|
|
XCTAssertEqual(
|
|
output.lyricsText,
|
|
"[Intro - whispered lead]\nFirst line\n\n[Chorus]\nApproved hook"
|
|
)
|
|
}
|
|
|
|
func testCompilerIncludesStyleInputsFromTheSongProject() throws {
|
|
let project = SongProject(
|
|
title: "Full Style",
|
|
idea: "Compile every approved style input",
|
|
genres: [
|
|
GenreStyle(id: "folk", name: "Folk"),
|
|
GenreStyle(id: "electronic", name: "Electronic")
|
|
],
|
|
moods: [MoodTag(id: "warm", name: "Warm")],
|
|
emotionalArc: [
|
|
EmotionalArcPoint(
|
|
id: "chorus-arc",
|
|
sectionID: "chorus",
|
|
emotion: "joyful",
|
|
energy: 8,
|
|
direction: "lift into release"
|
|
)
|
|
],
|
|
bpm: ManualAutoValue(mode: .manual, value: 108),
|
|
key: ManualAutoValue(mode: .manual, value: "D minor"),
|
|
scale: ManualAutoValue(mode: .manual, value: "Dorian"),
|
|
sections: [
|
|
SongSection(
|
|
id: "verse",
|
|
type: .verse,
|
|
title: "Verse",
|
|
emotion: "yearning",
|
|
energy: 3,
|
|
productionDirection: "intimate opening"
|
|
),
|
|
SongSection(id: "chorus", type: .chorus, title: "Chorus", order: 1)
|
|
],
|
|
vocalists: [
|
|
Vocalist(id: "lead", label: "Lead", voiceType: "clear alto", performanceStyle: "expressive")
|
|
],
|
|
productionDirections: [
|
|
ProductionDirection(id: "chorus-width", sectionID: "chorus", text: "wide chorus"),
|
|
ProductionDirection(id: "master", text: "warm tape saturation")
|
|
]
|
|
)
|
|
|
|
let output = try SongProjectPromptCompiler().compile(project: project)
|
|
|
|
XCTAssertEqual(
|
|
output.stylePrompt,
|
|
"Folk + Electronic; mood: Warm; Lead clear alto expressive; 108 BPM, key D minor, Dorian scale; emotion: Verse, yearning, energy 3; Chorus, joyful, energy 8, lift into release; production: Verse, intimate opening; Chorus, wide chorus; warm tape saturation"
|
|
)
|
|
}
|
|
}
|