Condividi tramite


La libreria NAudio (it-it)

Introduzione

In questo articolo vedremo la libreria NAudio, un progetto .NET opensource contenente una ventina di classi per l’elaborazione di file audio Mp3, Wave, Midi e Wma.

È stata sviluppata nel 2002 da Mark Heath e l’ultima release è del marzo 2015.

Quella che segue è una lista di quello che possiamo fare con Naudio:

  •   Scegliere un driver di uscita audio
  •   riprodurre un File MP3
  •   capire come convertire tra tutti i formati audio
  •   convertire un MP3 in WAV
  •   codificare in MP3 o altri formati di implementare MediaFoundationEncoder
  •   implementare la riproduzione "Fire e Forget”  (ad es. gioco di effetti sonori)
  •   riprodurre un File WAV
  •   utilizzare la classe WavFileWriter
  •   riprodurre lo streaming MP3
  •   implementare in loop Playback
  •   tagliare un File WAV
  •   riprodurre una sinusoide
  •   Unire file MP3
  •   convertire un file AIFF in file WAV
  •   lavoro con multi-canale Audio
  •   creare un tag ID3v2
  •   riprodurre e registrare audio allo stesso tempo
  •   Ricampionare l'Audio
  •   Input guidato Audio ricampionamento

Implementazione

Iniziamo subito a vedere come integrare la libreria nei nostri progetti WPF.

Lo faremo tramite Nuget, scaricabile a questo indirizzo: https://www.nuget.org/packages/NAudio

Oppure dalla gestione dei pacchetti Nuget.

Quindi, apriamo Visual Studio, creiamo un nuovo progetto WPF in VB e lo chiamiamo WpfNAudio.

Ora apriamo la gestione dei pacchetti di Nuget e cerchiamo Naudio:

Lo possiamo quindi installare da qui oppure tramite la console all’indirizzo sopra.

Una volta installato avremo la libreria referenziata, come nella seguente figura:

Vediamo ora alcuni esempi di utilizzo.

Riprodurre un file MP3

Mettiamo nella Window un pulsante per la riproduzione del file MP3.

Questo che segue è invece il Code-behind:

Imports System.ComponentModel

Imports NAudio

Imports NAudio.Wave

Class MainWindow

  Dim waveOutDevice As IWavePlayer

  Dim audioFileReader As AudioFileReader

  Private Sub Mp3Playbutton_Click(sender As Object, e As RoutedEventArgs) Handles Mp3Playbutton.Click

  Me.Opacity = 0.3

  Dim dlg As New Microsoft.Win32.OpenFileDialog()

  dlg.Filter = "Audio Files|*.mp3"

  dlg.ShowDialog()

  Me.Opacity = 1

  'Declarations required for audio out and the MP3 stream

  waveOutDevice = New WaveOut()

  audioFileReader = New AudioFileReader(dlg.FileName)

  waveOutDevice.Init(audioFileReader)

  waveOutDevice.Play()

  End Sub

  Private Sub MainWindow_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing

  If waveOutDevice IsNot Nothing Then

  waveOutDevice.[Stop]()

  End If

  audioFileReader.Dispose()

  audioFileReader = Nothing

  If waveOutDevice IsNot Nothing Then

  waveOutDevice.Dispose()

  waveOutDevice = Nothing

  End If

  End Sub

End Class

Convertire un file MP3 in Wave

Oltre al pulsante nello Xaml, mettiamo il seguente codice nel Code-behind.

  Private Sub ConvertMP3ToWavebutton_Click(sender As Object, e As RoutedEventArgs) Handles ConvertMP3ToWavebutton.Click

  Me.Opacity = 0.3

  Dim dlg As New Microsoft.Win32.OpenFileDialog()

  dlg.Filter = "MP3 Files|*.mp3"

  dlg.ShowDialog()

  Me.Opacity = 1

  Dim outputFileName As String = dlg.FileName

  outputFileName = outputFileName.Substring(0, dlg.FileName.Length - 4) + ".wav"

  Mp3ToWav(dlg.FileName, outputFileName)

  End Sub

  Public Shared Sub Mp3ToWav(mp3File As String, outputFile As String)

  Using reader As New Mp3FileReader(mp3File)

  WaveFileWriter.CreateWaveFile(outputFile, reader)

  End Using

  End Sub

Riproduzione di un file Wave

  Private Sub WavePlayerbutton_Click(sender As Object, e As RoutedEventArgs) Handles WavePlayerbutton.Click

  Me.Opacity = 0.3

  Dim dlg As New Microsoft.Win32.OpenFileDialog()

  dlg.Filter = "Wave Files|*.wav"

  dlg.ShowDialog()

  Me.Opacity = 1

  Using wfr = New WaveFileReader(dlg.FileName)

  Using wc As New WaveChannel32(wfr)

  Using audioOutput = New DirectSoundOut()

  audioOutput.Init(wc)

  audioOutput.Play()

  While audioOutput.PlaybackState <> PlaybackState.Stopped

  Thread.Sleep(20)

  End While

  audioOutput.[Stop]()

  End Using

  End Using

  End Using

  End Sub

Loop Play Back

  Private Sub LoopedPlaybackbutton_Click(sender As Object, e As RoutedEventArgs) Handles LoopedPlaybackbutton.Click

  If waveOut Is Nothing Then

  Me.Opacity = 0.3

  Dim dlg As New Microsoft.Win32.OpenFileDialog()

  dlg.Filter = "Wave Files|*.wav"

  dlg.ShowDialog()

  Me.Opacity = 1

  Dim reader As New WaveFileReader(dlg.FileName)

  Dim [loop] As New LoopStream(reader)

  waveOut = New WaveOut()

  waveOut.Init([loop])

  waveOut.Play()

  Else

  waveOut.[Stop]()

  waveOut.Dispose()

  waveOut = Nothing

  End If

  End Sub

E in fondo alla pagina, dopo End Class:

Public Class LoopStream

  Inherits WaveStream

  Private sourceStream As WaveStream

  ''' <summary>

  ''' Creates a new Loop stream

  ''' </summary>

  ''' <param name="sourceStream">The stream to read from. Note: the Read method of this stream should return 0 when it reaches the end

  ''' or else we will not loop to the start again.</param>

  Public Sub New(sourceStream As WaveStream)

  Me.sourceStream = sourceStream

  Me.EnableLooping = True

  End Sub

  ''' <summary>

  ''' Use this to turn looping on or off

  ''' </summary>

  Public Property EnableLooping() As Boolean

  Get

  Return m_EnableLooping

  End Get

  Set

  m_EnableLooping = Value

  End Set

  End Property

  Private m_EnableLooping As Boolean

  ''' <summary>

  ''' Return source stream's wave format

  ''' </summary>

  Public Overrides ReadOnly Property WaveFormat() As WaveFormat

  Get

  Return sourceStream.WaveFormat

  End Get

  End Property

  ''' <summary>

  ''' LoopStream simply returns

  ''' </summary>

  Public Overrides ReadOnly Property Length() As Long

  Get

  Return sourceStream.Length

  End Get

  End Property

  ''' <summary>

  ''' LoopStream simply passes on positioning to source stream

  ''' </summary>

  Public Overrides Property Position() As Long

  Get

  Return sourceStream.Position

  End Get

  Set

  sourceStream.Position = Value

  End Set

  End Property

  Public Overrides Function Read(buffer As Byte(), offset As Integer, count As Integer) As Integer

  Dim totalBytesRead As Integer = 0

  While totalBytesRead < count

  Dim bytesRead As Integer = sourceStream.Read(buffer, offset + totalBytesRead, count - totalBytesRead)

  If bytesRead = 0 Then

  If sourceStream.Position = 0 OrElse Not EnableLooping Then

  ' something wrong with the source stream

  Exit While

  End If

  ' loop

  sourceStream.Position = 0

  End If

  totalBytesRead += bytesRead

  End While

  Return totalBytesRead

  End Function

End Class

Rimozione di parte di file Wave

  Private Sub TagliaWavebutton_Click(sender As Object, e As RoutedEventArgs) Handles TagliaWavebutton.Click

  Me.Opacity = 0.3

  Dim dlg As New Microsoft.Win32.OpenFileDialog()

  dlg.Filter = "Wave Files|*.wav"

  dlg.ShowDialog()

  Me.Opacity = 1

  Dim outputFileName As String = dlg.FileName

  outputFileName = outputFileName.Substring(0, dlg.FileName.Length - 4) + "2.wav"

  Dim cutFromStart As TimeSpan, cutFromEnd As TimeSpan

  cutFromStart = New TimeSpan(0, 0, 10)

  cutFromEnd = New TimeSpan(0, 0, 30)

  TrimWavFile(dlg.FileName, outputFileName, cutFromStart, cutFromEnd)

  End Sub

  Public Shared Sub TrimWavFile(inPath As String, outPath As String, cutFromStart As TimeSpan, cutFromEnd As TimeSpan)

  Using reader As New WaveFileReader(inPath)

  Using writer As New WaveFileWriter(outPath, reader.WaveFormat)

  Dim bytesPerMillisecond As Integer = reader.WaveFormat.AverageBytesPerSecond / 1000

  Dim startPos As Integer = CInt(cutFromStart.TotalMilliseconds) * bytesPerMillisecond

  startPos = startPos - startPos Mod reader.WaveFormat.BlockAlign

  Dim endBytes As Integer = CInt(cutFromEnd.TotalMilliseconds) * bytesPerMillisecond

  endBytes = endBytes - endBytes Mod reader.WaveFormat.BlockAlign

  Dim endPos As Integer = CInt(reader.Length) - endBytes

  TrimWavFile(reader, writer, startPos, endPos)

  End Using

  End Using

  End Sub

  Private Shared Sub TrimWavFile(reader As WaveFileReader, writer As WaveFileWriter, startPos As Integer, endPos As Integer)

  reader.Position = startPos

  Dim buffer As Byte() = New Byte(1023) {}

  While reader.Position < endPos

  Dim bytesRequired As Integer = CInt(endPos - reader.Position)

  If bytesRequired > 0 Then

  Dim bytesToRead As Integer = Math.Min(bytesRequired, buffer.Length)

  Dim bytesRead As Integer = reader.Read(buffer, 0, bytesToRead)

  If bytesRead > 0 Then

  writer.Write(buffer, 0, bytesRead)

  End If

  End If

  End While

  End Sub

Conversione da Aiff in Wave

  Private Sub ConverteAiffInWavebutton_Click(sender As Object, e As RoutedEventArgs) Handles ConverteAiffInWavebutton.Click

  ConvertAiffToWav("C:\1.AIFF", "C:\1.WAV")

  End Sub

  Public Shared Sub ConvertAiffToWav(aiffFile As String, wavFile As String)

  Using reader As New AiffFileReader(aiffFile)

  Using writer As New WaveFileWriter(wavFile, reader.WaveFormat)

  Dim buffer As Byte() = New Byte(4095) {}

  Dim bytesRead As Integer = 0

  Do

  bytesRead = reader.Read(buffer, 0, buffer.Length)

  writer.Write(buffer, 0, bytesRead)

  Loop While bytesRead > 0

  End Using

  End Using

  End Sub

End Class

Conclusioni

Abbiamo visto in questo articolo un delle migliori librerie per l’editing audio e per ascoltare la vostra libreria musicale.

Abbiamo poi visto alcuni esempi su come usare la libreria per semplici conversioni, ascolto o tagli.