Private/Invoke-AcoustIdFingerprintInternal.ps1
|
function Invoke-AcoustIdFingerprintInternal { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$InputPath ) $reader = $null try { Write-Verbose "Processing file: $InputPath" $extension = [System.IO.Path]::GetExtension($InputPath).ToLower() switch ($extension) { {$_ -in '.aiff', '.aif'} { $reader = [NAudio.Wave.AiffFileReader]::new($InputPath) } '.wav' { $reader = [NAudio.Wave.WaveFileReader]::new($InputPath) } '.mp3' { try { $mp3ReaderType = [Type]::GetType('NAudio.Mpeg.Mp3FileReader') if ($mp3ReaderType) { $reader = [Activator]::CreateInstance($mp3ReaderType, @($InputPath)) } else { Write-Error "MP3 reader not available. Ensure NAudio.Mpeg.dll is in lib folder." return } } catch { Write-Error "Failed to open MP3 file. Ensure NAudio.Mpeg.dll is available. Error: $_" return } } '.flac' { try { $flacReaderType = [Type]::GetType('NAudio.Flac.FlacFileReader') if ($flacReaderType) { $reader = [Activator]::CreateInstance($flacReaderType, @($InputPath)) } else { Write-Error "FLAC reader not available. Ensure NAudio.Flac.dll is in lib folder." return } } catch { Write-Error "Failed to open FLAC file. Ensure NAudio.Flac.dll is available. Error: $_" return } } '.m4a' { Write-Error "M4A/AAC format is not directly supported by NAudio. Consider converting to AIFF, WAV, FLAC, or MP3." return } default { throw "Unsupported audio format: $extension. Supported formats: .aiff, .aif, .wav, .mp3, .flac" } } $duration = $reader.TotalTime.TotalSeconds $waveFormat = $reader.WaveFormat $sampleRate = $waveFormat.SampleRate $channels = $waveFormat.Channels $bitsPerSample = $waveFormat.BitsPerSample Write-Verbose "Audio format: $($sampleRate)Hz, $channels channels, $bitsPerSample-bit" $ctx = New-ChromaprintContext -SampleRate $sampleRate -Channels $channels $sourceBytesPerSample = $bitsPerSample / 8 $sourceFrameSize = $sourceBytesPerSample * $channels $bufferSize = 4096 * $sourceFrameSize $buffer = New-Object byte[] $bufferSize while ($true) { $bytesRead = $reader.Read($buffer, 0, $buffer.Length) if ($bytesRead -le 0) { break } $frameCount = [int]($bytesRead / $sourceFrameSize) $completeFrameBytes = $frameCount * $sourceFrameSize if ($completeFrameBytes -le 0) { continue } $int16Buffer = $null if ($bitsPerSample -eq 16) { $sampleCount = $completeFrameBytes / 2 $int16Buffer = New-Object short[] $sampleCount [System.Buffer]::BlockCopy($buffer, 0, $int16Buffer, 0, $completeFrameBytes) } elseif ($bitsPerSample -eq 24) { $sampleCount = $frameCount * $channels $int16Buffer = New-Object short[] $sampleCount for ($i = 0; $i -lt $sampleCount; $i++) { $byteOffset = $i * 3 $byte1 = $buffer[$byteOffset] $byte2 = $buffer[$byteOffset + 1] $byte3 = $buffer[$byteOffset + 2] $sample32 = [int]($byte1 -bor ($byte2 -shl 8) -bor ($byte3 -shl 16)) if ($sample32 -band 0x800000) { $sample32 = $sample32 -bor 0xFF000000 } $int16Buffer[$i] = [short]($sample32 -shr 8) } } else { throw "Unsupported bit depth: $bitsPerSample-bit. Only 16-bit and 24-bit audio are supported." } try { $ctx.Feed($int16Buffer, $int16Buffer.Length) } catch { Write-Error "Feed failed: $_" throw } } Invoke-ChromaprintMethod -Instance $ctx -MethodNames @('Finish') | Out-Null $fingerprint = Invoke-ChromaprintMethod -Instance $ctx -MethodNames @('GetFingerprint', 'Fingerprint') [AcoustIdFingerprintResult]::new($InputPath, $duration, ([string]$fingerprint)) } finally { if ($reader) { $reader.Dispose() } } } |