using System; using Paca.Core; using Xunit; namespace Paca.Tests.Core; public class AudioPitchShiftEngineGateTests { [Fact] public void Gate385_AudioPitchShift_CalculatesAccuratePitchScale() { // 0 semitones -> 1.0 Assert.Equal(1.0, AudioPitchShiftEngine.CalculatePitchScale(0.0), 4); // +12 semitones (1 octave up) -> 2.0 Assert.Equal(2.0, AudioPitchShiftEngine.CalculatePitchScale(12.0), 4); // -12 semitones (1 octave down) -> 0.5 Assert.Equal(0.5, AudioPitchShiftEngine.CalculatePitchScale(-12.0), 4); // +1 semitone -> ~1.0595 Assert.Equal(1.0595, AudioPitchShiftEngine.CalculatePitchScale(1.0), 4); } [Fact] public void Gate386_AudioPitchShift_BuildsFfmpegFilterChain() { // +2 semitones (scale ~ 1.1225) var filter = AudioPitchShiftEngine.BuildPitchShiftFilter(semitones: 2.0, sampleRate: 44100); Assert.Contains("asetrate=", filter); Assert.Contains("atempo=", filter); Assert.Contains("aresample=44100", filter); } [Fact] public void Gate387_AudioPitchShift_ClampsExtremeSemitoneRanges() { var clampedHigh = AudioPitchShiftEngine.ClampSemitones(24.0); Assert.Equal(12.0, clampedHigh); var clampedLow = AudioPitchShiftEngine.ClampSemitones(-30.0); Assert.Equal(-12.0, clampedLow); } [Fact] public void Gate388_AudioPitchShift_BuildsFullCommandLine_WithVideoCopy() { var cmd = AudioPitchShiftEngine.BuildPitchShiftCommandLine( inputPath: "C:\\music\\karaoke.mp4", outputPath: "C:\\music\\karaoke_plus1.mp4", semitones: 1.0, isAudioOnly: false, sampleRate: 48000 ); Assert.Contains("-i \"C:\\music\\karaoke.mp4\"", cmd); Assert.Contains("-c:v copy", cmd); Assert.Contains("-filter:a \"asetrate=", cmd); Assert.Contains("aresample=48000", cmd); Assert.Contains("-c:a aac -b:a 192k", cmd); Assert.EndsWith("\"C:\\music\\karaoke_plus1.mp4\" -y", cmd); } }