41 lines
3.4 KiB
PowerShell
41 lines
3.4 KiB
PowerShell
param([Parameter(Mandatory)][string]$ReferencePath,[Parameter(Mandatory)][string]$CapturedPath,[Parameter(Mandatory)][string]$WrongReferencePath,[Parameter(Mandatory)][string]$EvidenceDir)
|
|
$ErrorActionPreference='Stop'
|
|
New-Item -ItemType Directory -Path $EvidenceDir -Force | Out-Null
|
|
$checks=[Collections.Generic.List[object]]::new()
|
|
function Match([string]$Name,[string]$Reference,[string]$Captured,[bool]$Expected) {
|
|
$path=Join-Path $EvidenceDir "$Name.json"
|
|
& pwsh -NoProfile -File (Join-Path $PSScriptRoot 'compare-audio.ps1') -ReferencePath $Reference -CapturedPath $Captured -OutputPath $path -RequireFullSpeech
|
|
$code=$LASTEXITCODE;$record=Get-Content -LiteralPath $path -Raw | ConvertFrom-Json
|
|
$checks.Add(@{name=$Name;expectedPassed=$Expected;exitCode=$code;record=$record})
|
|
if ($record.passed -ne $Expected -or ($Expected -and $code -ne 0) -or (!$Expected -and $code -eq 0)) { throw "PCM negative control mismatch: $Name" }
|
|
return $record
|
|
}
|
|
try {
|
|
$positive=Match 'positive-full-speech' $ReferencePath $CapturedPath $true
|
|
Add-Type -TypeDefinition @'
|
|
using System;
|
|
using System.IO;
|
|
public static class NativeAudioControls {
|
|
public static void Create(string input,string output,string kind,double onset,double duration) {
|
|
byte[] bytes=File.ReadAllBytes(input);int rate=BitConverter.ToInt32(bytes,24),start=(int)Math.Round(onset*rate),length=(int)Math.Round(duration*rate),cut=rate/4,middle=start+(int)(rate*.85);
|
|
if(BitConverter.ToInt16(bytes,20)!=1 || BitConverter.ToInt16(bytes,22)!=1 || BitConverter.ToInt16(bytes,34)!=16 || System.Text.Encoding.ASCII.GetString(bytes,36,4)!="data") throw new Exception("Canonical monoPCM16 WAV required");
|
|
short[] data=new short[(bytes.Length-44)/2];Buffer.BlockCopy(bytes,44,data,0,bytes.Length-44);
|
|
if(start<0 || start+length>data.Length || length<rate)throw new Exception("Complete control speech required");
|
|
if(kind=="duplicate") {var longer=new short[data.Length+cut];Array.Copy(data,0,longer,0,middle);Array.Copy(data,middle-cut,longer,middle,cut);Array.Copy(data,middle,longer,middle+cut,data.Length-middle);data=longer;}
|
|
else if(kind=="noise") {var random=new Random(42);for(int i=0;i<data.Length;i++)data[i]=(short)random.Next(-4096,4097);}
|
|
else {int offset=kind=="front"?start:kind=="back"?start+length-cut:middle;Array.Clear(data,offset,cut);}
|
|
using(var w=new BinaryWriter(File.Create(output))) {w.Write(System.Text.Encoding.ASCII.GetBytes("RIFF"));w.Write(36+data.Length*2);w.Write(System.Text.Encoding.ASCII.GetBytes("WAVEfmt "));w.Write(16);w.Write((short)1);w.Write((short)1);w.Write(rate);w.Write(rate*2);w.Write((short)2);w.Write((short)16);w.Write(System.Text.Encoding.ASCII.GetBytes("data"));w.Write(data.Length*2);foreach(short sample in data)w.Write(sample);}
|
|
}
|
|
}
|
|
'@
|
|
foreach($kind in @('front','back','middle','duplicate','noise')) {
|
|
$path=Join-Path $EvidenceDir "$kind.wav";[NativeAudioControls]::Create((Resolve-Path $CapturedPath).Path,$path,$kind,$positive.onsetSeconds,$positive.referenceDurationSeconds)
|
|
Match $kind $ReferencePath $path $false | Out-Null
|
|
}
|
|
Match 'wrong-clip' $WrongReferencePath $CapturedPath $false | Out-Null
|
|
$passed=$true
|
|
} finally {
|
|
@{sourceCommit=(& git rev-parse HEAD);sourceDirty=[bool](& git status --porcelain);passed=($passed -eq $true);checks=$checks.ToArray();finishedUtc=[DateTime]::UtcNow.ToString('o')} | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $EvidenceDir 'regression.json') -Encoding utf8
|
|
}
|
|
Write-Host 'Native PCM positive and six meaningful negative controls passed.'
|