Reputation: 140
EDIT: Solved in self-answer below.
I've looked all over but I can't find anything useful for playing audio files with volume control. I tried XNA; SLIMDX and "Microsoft.VisualBasic.Devices.Audio" but nothing helped. The options I found which had volume control were too complex and I couldn't figure out how to use, and the method I have currently doesn't let you do anything more than play(background with or without loop, or pause execution until end of play) and stop.
Here's my current code:
Dim AD As New Microsoft.VisualBasic.Devices.Audio
Sub Play()
Dim af() As Byte = IO.File.ReadAllBytes("music.wav")
AD.Play(af, AudioPlayMode.BackgroundLoop)
End Sub
This loops "music.wav" in the background, but i cannot pause/seek it or control the volume. Is there any simple way(like the above) to play audio files from a buffer and control the audio volume? I've looked all over but nothing I've found works for my project.
System: Win7 64-bit
VS version: 2010
Language: VB.net
Oh one more thing, buffering the audio first is something I need for my solution as well(as you can see in my current code)
Does anyone have a solution to this? :)
Upvotes: 2
Views: 14422
Reputation: 2085
As there seems to be little documentation on using naudio in VB.NET, rather than the C# examples found everywhere, and further to @user1666788's comments, this is a simple way of making it play an MP3 file for VB.NET, rather than a WAV.
Public Shared Wave1 As New NAudio.Wave.WaveOut 'Wave out device for playing the sound
Public Sub btn_PlayPause_Click(sender As Object, e As EventArgs) Handles btn_PlayPause.Click
Dim file As String = "C:\test.mp3"
Dim data As New NAudio.Wave.Mp3FileReader(file)
Wave1.Init(data)
Wave1.Play()
End Sub
Upvotes: 0
Reputation: 1
hey i hav make a class to handle wave(pcm) file hope this will help u.. its not completed yet but might be helpful.
Imports System.IO
Imports System.Runtime.InteropServices Imports System.ComponentModel
Public Structure WaveHeader Public Chunk As Char() Public ChunkSize As Int32 Public Format As Char() Public SubChunk1 As Char() Public SubChunk1Size As Int32 Public AudioFormat As Int16 Public Channels As Int16 Public SampleRate As Int32 Public ByteRate As Int32 Public BlockAlign As Int16 Public BitsPerSample As Int16 Public SubChunk2 As Char() Public SubChunk2Size As Int32 End Structure
Public Enum State None Playing Paused Stopped Finished End Enum
Public Class wav
Private watch As New Stopwatch
Private WithEvents timer As New Timer
Private mystate As State = State.None
Private myheader As WaveHeader
Private myurl As String = Nothing
Private mytotaltime As Double = 0
Private Declare Function SetProcessWorkingSetSize Lib "kernel32.dll" (ByVal process As IntPtr, ByVal minimumWorkingSetSize As Integer, ByVal maximumWorkingSetSize As Integer) As Integer
Event OnPlayStateChange(ByVal e As State)
Public Shared Sub FlushMemory()
GC.Collect()
GC.WaitForPendingFinalizers()
If (Environment.OSVersion.Platform = PlatformID.Win32NT) Then
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1)
End If
End Sub
Sub New()
timer.Interval = 1
timer.Start()
End Sub
Function readheader(ByVal url As String)
Dim fh As WaveHeader
Dim stream As New FileStream(url, FileMode.Open)
Dim br As New BinaryReader(stream)
fh.Chunk = br.ReadChars(4)
fh.ChunkSize = br.ReadInt32
fh.Format = br.ReadChars(4)
fh.SubChunk1 = br.ReadChars(4)
fh.SubChunk1Size = br.ReadInt32
fh.AudioFormat = br.ReadInt16
fh.Channels = br.ReadInt16
fh.SampleRate = br.ReadInt32
fh.ByteRate = br.ReadInt32
fh.BlockAlign = br.ReadInt16
fh.BitsPerSample = br.ReadInt16
For i = 1 To fh.SubChunk1Size - 16
br.ReadByte()
Next
fh.SubChunk2 = br.ReadChars(4)
fh.SubChunk2Size = br.ReadInt32
br.Close()
stream.Close()
Return Header2String(fh)
End Function
Function Header2String(ByVal fh As WaveHeader)
Dim t As String = ""
t &= "Chunk " & fh.Chunk & Environment.NewLine
t &= "Chunksize " & fh.ChunkSize & Environment.NewLine
t &= "Format " & fh.Format & Environment.NewLine
t &= "subChunk1 " & fh.SubChunk1 & Environment.NewLine
t &= "subchunk1size " & fh.SubChunk1Size & Environment.NewLine
t &= "PCM " & fh.AudioFormat & Environment.NewLine
t &= "Channels " & fh.Channels & Environment.NewLine
t &= "Samplerate " & fh.SampleRate & Environment.NewLine
t &= "ByteRate " & fh.ByteRate & Environment.NewLine
t &= "Block Align " & fh.BlockAlign & Environment.NewLine
t &= "Bits/Sample " & fh.BitsPerSample & Environment.NewLine
t &= "subChunk2 " & fh.SubChunk2 & Environment.NewLine
t &= "subChunk2size " & fh.SubChunk2Size & Environment.NewLine
Return t
End Function
Function StopAudio()
My.Computer.Audio.Stop()
watch.Stop()
watch.Reset()
If PlayState = State.Playing Or PlayState = State.Paused Then
mystate = State.Stopped
End If
Return 0
End Function
Function playAudio(ByVal url As String)
If My.Computer.FileSystem.FileExists(url) Then
Try
My.Computer.Audio.Play(SongStream(url, 0), AudioPlayMode.Background)
'My.Computer.Audio.Play(fast(url, 0, CDbl(form1.TextBox4.Text)), AudioPlayMode.Background)
watch.Restart()
mystate = State.Playing
RaiseEvent OnPlayStateChange(State.Playing)
myurl = url
Catch ex As Exception
Throw New Exception("Error! Can't Play The File.")
'MsgBox(ex.Message)
End Try
Else
Throw New Exception("File Not Exist.")
End If
Return 0
End Function
Function PauseAudio()
If PlayState = State.Playing Then
My.Computer.Audio.Stop()
watch.Stop()
mystate = State.Paused
RaiseEvent OnPlayStateChange(State.Paused)
End If
Return 0
End Function
Function ResumeAudio()
If PlayState = State.Paused And IsNothing(URL) = False Then
Try
My.Computer.Audio.Play(SongStream(URL, time), AudioPlayMode.Background)
watch.Start()
mystate = State.Playing
RaiseEvent OnPlayStateChange(State.Playing)
Catch : End Try
End If
Return 0
End Function
Private Function fast(ByVal url As String, ByVal position As Double, ByVal speed As Single)
Dim fh As New WaveHeader
Dim stream As New FileStream(url, FileMode.Open)
Dim br As New BinaryReader(stream)
fh.Chunk = br.ReadChars(4)
fh.ChunkSize = br.ReadInt32
fh.Format = br.ReadChars(4)
fh.SubChunk1 = br.ReadChars(4)
fh.SubChunk1Size = br.ReadInt32
fh.AudioFormat = br.ReadInt16
fh.Channels = br.ReadInt16
fh.SampleRate = br.ReadInt32
fh.ByteRate = br.ReadInt32
fh.BlockAlign = br.ReadInt16
fh.BitsPerSample = br.ReadInt16
fh.SampleRate *= speed
fh.ByteRate *= speed
For i = 1 To fh.SubChunk1Size - 16
br.ReadChar()
Next
stream.Position = fh.SubChunk1Size + 20
fh.SubChunk2 = br.ReadChars(4)
fh.SubChunk2Size = br.ReadInt32
If fh.Channels = 6 Then
fh.Channels = 2
fh.BlockAlign = fh.Channels * fh.BitsPerSample / 8
fh.SampleRate = fh.SampleRate * (6 / fh.Channels)
End If
position = Math.Round(CInt(position / 1000) * fh.ByteRate)
If position >= fh.SubChunk2Size Then
Throw New Exception("Songs isn't that long")
End If
mytotaltime = Math.Round(fh.SubChunk2Size / fh.ByteRate)
fh.SubChunk2Size -= position
Dim header() As Byte = {Asc("R"), Asc("I"), Asc("F"), Asc("F"), 0, 0, 0, 0, Asc("W"), Asc("A"), Asc("V"), Asc("E"), Asc("f"), Asc("m"), Asc("t"), Asc(" "), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Asc("d"), Asc("a"), Asc("t"), Asc("a"), 0, 0, 0, 0}
BitConverter.GetBytes(fh.SubChunk2Size).CopyTo(header, 40)
BitConverter.GetBytes(fh.BitsPerSample).CopyTo(header, 34)
BitConverter.GetBytes(fh.BlockAlign).CopyTo(header, 32)
BitConverter.GetBytes(fh.ByteRate).CopyTo(header, 28)
BitConverter.GetBytes(fh.SampleRate).CopyTo(header, 24)
BitConverter.GetBytes(fh.Channels).CopyTo(header, 22)
BitConverter.GetBytes(fh.AudioFormat).CopyTo(header, 20)
BitConverter.GetBytes(16).CopyTo(header, 16)
BitConverter.GetBytes(fh.SubChunk2Size + 36).CopyTo(header, 4)
myheader = fh
Dim audio(fh.SubChunk2Size + 44) As Byte
header.CopyTo(audio, 0)
stream.Position = position
br.ReadBytes(fh.SubChunk2Size).CopyTo(audio, 44)
br.Dispose()
stream.Dispose()
br = Nothing
stream = Nothing
Return audio
End Function
Private Function SongStream(ByVal url As String, ByVal position As Double)
Dim fh As New WaveHeader
Dim stream As New FileStream(url, FileMode.Open)
Dim br As New BinaryReader(stream)
fh.Chunk = br.ReadChars(4)
fh.ChunkSize = br.ReadInt32
fh.Format = br.ReadChars(4)
fh.SubChunk1 = br.ReadChars(4)
fh.SubChunk1Size = br.ReadInt32
fh.AudioFormat = br.ReadInt16
fh.Channels = br.ReadInt16
fh.SampleRate = br.ReadInt32
fh.ByteRate = br.ReadInt32
fh.BlockAlign = br.ReadInt16
fh.BitsPerSample = br.ReadInt16
For i = 1 To fh.SubChunk1Size - 16
br.ReadChar()
Next
stream.Position = fh.SubChunk1Size + 20
fh.SubChunk2 = br.ReadChars(4)
fh.SubChunk2Size = br.ReadInt32
If fh.Channels = 6 Then
fh.Channels = 2
fh.BlockAlign = fh.Channels * fh.BitsPerSample / 8
fh.SampleRate = fh.SampleRate * (6 / fh.Channels)
End If
position = Math.Round(CInt(position / 1000) * fh.ByteRate)
If position >= fh.SubChunk2Size Then
Throw New Exception("Songs isn't that long")
End If
mytotaltime = Math.Round(fh.SubChunk2Size / fh.ByteRate)
fh.SubChunk2Size -= position
Dim header() As Byte = {Asc("R"), Asc("I"), Asc("F"), Asc("F"), 0, 0, 0, 0, Asc("W"), Asc("A"), Asc("V"), Asc("E"), Asc("f"), Asc("m"), Asc("t"), Asc(" "), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Asc("d"), Asc("a"), Asc("t"), Asc("a"), 0, 0, 0, 0}
BitConverter.GetBytes(fh.SubChunk2Size).CopyTo(header, 40)
BitConverter.GetBytes(fh.BitsPerSample).CopyTo(header, 34)
BitConverter.GetBytes(fh.BlockAlign).CopyTo(header, 32)
BitConverter.GetBytes(fh.ByteRate).CopyTo(header, 28)
BitConverter.GetBytes(fh.SampleRate).CopyTo(header, 24)
BitConverter.GetBytes(fh.Channels).CopyTo(header, 22)
BitConverter.GetBytes(fh.AudioFormat).CopyTo(header, 20)
BitConverter.GetBytes(16).CopyTo(header, 16)
BitConverter.GetBytes(fh.SubChunk2Size + 36).CopyTo(header, 4)
myheader = fh
Dim audio(fh.SubChunk2Size + 44) As Byte
header.CopyTo(audio, 0)
stream.Position = position
br.ReadBytes(fh.SubChunk2Size).CopyTo(audio, 44)
br.Dispose()
stream.Dispose()
br = Nothing
stream = Nothing
Return audio
End Function
<Browsable(False)> ReadOnly Property PlayState
Get
Return mystate
End Get
End Property
<Browsable(False)> ReadOnly Property URL
Get
Return myurl
End Get
End Property
ReadOnly Property TotalTime
Get
Return mytotaltime
End Get
End Property
ReadOnly Property time
Get
Return watch.ElapsedMilliseconds
End Get
End Property
ReadOnly Property timestamp
Get
Return watch.Elapsed.ToString
End Get
End Property
Private Sub timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timer.Tick
If Not TotalTime = 0 Then
If TotalTime <= time / 1000 Then
watch.Stop()
watch.Reset()
mystate = State.Finished
RaiseEvent OnPlayStateChange(State.Finished)
End If
End If
FlushMemory()
End Sub
ReadOnly Property SongHeader As WaveHeader
Get
Return myheader
End Get
End Property
End Class
Public Class spactrum
Dim h As WaveHeader
Function readheader(ByVal url As String)
Dim fh As WaveHeader
Dim stream As New FileStream(url, FileMode.Open)
Dim br As New BinaryReader(stream)
fh.Chunk = br.ReadChars(4)
fh.ChunkSize = br.ReadInt32
fh.Format = br.ReadChars(4)
fh.SubChunk1 = br.ReadChars(4)
fh.SubChunk1Size = br.ReadInt32
fh.AudioFormat = br.ReadInt16
fh.Channels = br.ReadInt16
fh.SampleRate = br.ReadInt32
fh.ByteRate = br.ReadInt32
fh.BlockAlign = br.ReadInt16
fh.BitsPerSample = br.ReadInt16
For i = 1 To fh.SubChunk1Size - 16
br.ReadByte()
Next
fh.SubChunk2 = br.ReadChars(4)
fh.SubChunk2Size = br.ReadInt32
h = fh
Return br.ReadBytes(fh.SubChunk2Size)
End Function
Function showit()
Dim b As New Bitmap(500, 200)
Dim g As Graphics = Graphics.FromImage(b)
Dim d() As Byte = readheader("songs\s.wav")
'Dim t As Integer = d.Count
For i = 0 To d.Count - 1
Dim x = CInt((i / d.Count) * 500)
Dim y = CInt(d(i).ToString) - 200
g.DrawLine(Pens.Black, x, 0, x, y)
Next
'g.FillEllipse(Brushes.Black, 0, 0, 500, 300)
Return b.Clone
End Function
End Class
Upvotes: 0
Reputation: 140
I found the answer after a bit of searching around so here's the solution I found for my question:
Download Naudio and add the references to your project.
Then the following code is how to use it for loading audio from a buffer:
Dim Wave1 As New NAudio.Wave.WaveOut 'Wave out device for playing the sound
Dim xa() As Byte = IO.File.ReadAllBytes("C:\YourPath\YourWave.wav") 'Your Buffer
Sub PlaySound()
Dim data As New IO.MemoryStream(xa) 'Data stream for the buffer
Wave1.Init(New NAudio.Wave.BlockAlignReductionStream(NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(New NAudio.Wave.WaveFileReader(data))))
Wave1.Volume = 0.1 'Sets the Volume to 10%
Wave1.Play()
End Sub
WaveFileReader can be changed to whichever reader you need(i.e. the MP3 one for ".mp3" files) to load your audio file, but the code works as-is for loading ".wav" files.
oh and also, don't forget to
WaveOut.Dispose()
when you're done to avoid errors.
I hope my research helps somebody :)
Upvotes: 4