Convert-AudioWavFile.ps1

function Convert-AudioWavFile 
{
  <#
      .SYNOPSIS
      Converts WAV audio file in audio formats that can be played back by simple MP3 Players such as DFPlayer Mini
 
      .DESCRIPTION
      Uses ffmpeg.exe to convert the audio file format of WAV audio files either to supported WAV files or MP3.
      On Windows, if ffmpeg.exe is not present, it will be downloaded automatically and stored in a temp folder.
      On other operating systems, ffmpeg.exe needs to be manually downloaded (i.e. from https://ffbinaries.com/downloads)
      and placed here: $env:temp\ffmpeg\ffmpeg.exe
 
      .PARAMETER Path
      Path to original WAV audio file
 
      .PARAMETER OutPath
      Path to new audio file to be created
 
      .PARAMETER CreateMp3
      When specified, the new audio file is a mp3 file. Else, it remains a wav file.
 
      .PARAMETER Force
      Overwrites target file when it exists.
 
      .EXAMPLE
      Convert-AudioWavFile -Path c:\test\test.wav -OutPath c:\test\test.mp3 -Force
      Converts wav file to wav encoding that can be played back by DFPLayer Mini. If the target file exists, it will be overwritten.
 
      .EXAMPLE
      Convert-AudioWavFile -Path c:\test\test.wav -OutPath c:\test\new.wav
      Converts wav file to a new wav file using encoding that can be played back by DFPlayer Mini. If the target file exists, an exception is raised.
 
      .EXAMPLE
      Convert-AudioWavFile -Path c:\test\test.wav
      Converts wav file and replaces the original wav file with the new wav file (in-place conversion). Make sure you have a backup of the original audio file or do not need it anymore. It will be lost during this type of conversion.
  #>



  param
  (
    [String]
    [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Alias('FullName')]
    $Path,
    
    [String]
    [Parameter(Mandatory,ValueFromPipelineByPropertyName)]
    $OutPath,
    
    [switch]
    $CreateMp3, 
    
    [switch]
    $Force
  )
  
  begin
  {    
    $executablePath = Assert-FfmpegIsPresent
    
    # when used in a pipeline, and when in-place conversion is specified,
    # this seems to re-trigger directory enumeration. Until a clear reason
    # for this has been established, a hashtable takes care that no
    # redundant conversion takes place
    $done = @{}
  }
  process
  {
    # make sure we process each file only once:
    if ($done.ContainsKey($Path)) { return }
    $done[$Path]=$true
    
    $file = Get-Item -Path $Path
    $extension = $file.Extension.ToLower()
    if ($extension -ne '.wav')
    {
      throw "No WAV Audio File: $Path"
    }
    
    # if parameter -OutPath was not specified, do an in-place conversion
    $tempFile = if (!$PSBoundParameters.ContainsKey('OutPath'))
    {
      Write-Verbose "Converting '$Path' (in-place)."
      $OutPath = $Path
      # move original file
      $tempName = (New-Guid).Guid + $file.Extension
      $destinationPath = Join-Path -Path $env:temp -ChildPath $tempName
      $newFile = $file | Move-Item -Destination $destinationPath -PassThru
      $Path = $newFile.FullName
      # return renamed file so it can later be restored or deleted:
      $newFile
    }
    
    
    if ($CreateMp3)
    {
      $OutPath = [system.io.Path]::ChangeExtension($OutPath, 'mp3')
    }
     
    Write-Verbose "New File: '$OutPath'."
    $exists = Test-Path -LiteralPath $OutPath -PathType Leaf
    if ($exists -and $Force)
    {
      Write-Verbose "Target file exists, deleting."
      Remove-Item -LiteralPath $OutPath -Force
    }
        
    $exists = Test-Path -LiteralPath $OutPath -PathType Leaf
    if (!$exists)
    {
      # does the target folder exist?
      $parent = $OutPath | Split-Path
      $exists = Test-Path -Path $parent -PathType Container
      if (!$exists)
      {
        Write-Verbose "Target folder does not exist: '$parent'. Creating."
        $null = New-Item -Path $parent -ItemType Directory
      }
    
      if ($CreateMp3)
      {
        
        $null = & $executablePath -n -i $Path -ar 44100 -ac 1 -b:a 128k $OutPath *>&1
      }
      else
      {
        $null = & $executablePath -n -i $Path -c:a adpcm_ima_wav -ar 44100 -ac 1 $OutPath *>&1
      }
      
      # test whether output file was successfully generated
      $exists = Test-Path -LiteralPath $OutPath -PathType Leaf
      if (!$exists)
      {
        # if we renamed the original file, restore it:
        if ($tempFile)
        {
          $realName = $Path | Split-Path -Leaf
          $tempFile | Rename-Item -NewName $realName
        }
        Write-Verbose "Unable to generate $OutPath."
        throw "Unable to convert '$Path' to '$OutPath'"
      }
      else
      {
        # remove renamed original file
        if ($tempFile)
        {
          $tempFile | Remove-Item 
          Write-Verbose "Successfully generated $OutPath."
        }
        
      }
    }
    else
    {
      Write-Warning "Target file '$OutPath' exists. Use -Force to overwrite."
    }
  }
}