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.