Objeto My.Resources y control Windows Media Player (Visual Basic 2013)

Iniciado por Tazmania40, 26 Mayo 2016, 14:02 PM

0 Miembros y 1 Visitante están viendo este tema.

Tazmania40

Buenas queria realizar 2 preguntas, con Windows Forms.

1º El Objeto My.Resources permite añadir otro tipo de archivos de audio que no sean WAV, esto es para utilizarlo con el control Windows Media Player en Visual Basic 2013.

2º Hay alguna forma de añadir el sonido, aunque sea WAV sino se puede otro formato en el control Windows Media Player desde los recursos (My.Resources). El código que utilizo es este, pero me gustaría compilar todo sin utilizar archivos externos.

Código (vbnet) [Seleccionar]
AxWindowsMediaPlayer1.URL = "C:\Temp\Sonido1.wav"

Me gustaria utilizar esta forma y he probado de muchas maneras y no lo consigo.

Código (vbnet) [Seleccionar]
My.Computer.Audio.Play(My.Resources.Sonido1, AudioPlayMode.BackgroundLoop)

Muchas gracias
Saludos

Eleкtro

#1
Cita de: Tazmania40 en 26 Mayo 2016, 14:02 PM1º El Objeto My.Resources permite añadir otro tipo de archivos de audio que no sean WAV, esto es para utilizarlo con el control Windows Media Player en Visual Basic 2013.

Sí, puedes añadir cualquier tipo de archivo a la tabla de recursos, ahora, el único formato de audio que Visual Studio puede identificar, es .wav, así que tus archivos mp3 y etc. se añadirán en la sección "Files".




Cita de: Tazmania40 en 26 Mayo 2016, 14:02 PM2º Hay alguna forma de añadir el sonido, aunque sea WAV sino se puede otro formato en el control Windows Media Player desde los recursos (My.Resources).

Puedes extraer los bytes del recurso para crear un archivo local, y entonces, cargarlo en el componente de WMP.

Código (vbnet) [Seleccionar]

''' <summary>
''' Extracts a resource to disk.
''' </summary>
<DebuggerStepThrough>
Public Shared Sub ExtractResourceToDisk(ByVal resource As Byte(),
                                       ByVal targetFilepath As String,
                                       Optional ByVal overwrite As Boolean = False)

   Dim mode As FileMode
   If overwrite Then
       mode = FileMode.Create
   Else
       mode = FileMode.CreateNew
   End If

   Dim bufferSize As Integer = 4096
   Using fs As New FileStream(targetFilepath, mode, FileAccess.Write, FileShare.Read, bufferSize)
       fs.Write(resource, 0, resource.Length)
   End Using

End Sub


Ejemplo de uso:
Código (vbnet) [Seleccionar]
Dim filepath As String = Path.GetTempFileName()
Dim fileUri As New Uri(String.Format("file:///{0}", filepath))
ExtractResourceToDisk(My.Resources.MyAudioFile1, filepath, overwrite:=True)

AxWindowsMediaPlayer1.URL = fileUri.AbsoluteUri


PD: Desconozco si el componente ActiveX de WMP acepta el formato de URI, es de suponer que si, pero de lo contrario modifica el código para usar una ruta de archivo regular.




Por último, quiero añadir que en mi API ElektroKit puedes encontrar un reproductor de audio basado en MCI.
Soporta MP3 y WAVE entre otros, y tiene métodos para pausar, reanudar, detener, saltar a...

(click en la imagen para ir al código fuente)


Ejemplo de uso:
Código (vbnet) [Seleccionar]
Dim player As New AudioPlayer

Sub Button_LoadFile_Click() Handles Button_LoadFile.Click

   If Not player.IsFileLoaded Then
       player.LoadFile("C:\File.wav")
   End If

End Sub

Sub Button_Play_Click() Handles Button_Play.Click

   If (player.Status <> PlayerStatus.Playing) Then
       player.Play(AudioPlayMode.Background)
   End If

End Sub

Sub Button_Stop_Click() Handles Button_Stop.Click

   If (player.Status <> PlayerStatus.Stopped) Then
       player.Stop()
   End If

End Sub

Sub Button_PauseResume_Click() Handles Button_PauseResume.Click

   If (player.Status = PlayerStatus.Playing) Then
       player.Pause()

   ElseIf (player.Status = PlayerStatus.Paused) Then
       player.Resume()

   End If

End Sub

Private Sub Button_SeekBackward_Click(sender As Object, e As EventArgs) Handles Button_SeekBackward.Click

   Dim currentPosition As Long = CLng(player.Position.TotalMilliseconds)

   If ((currentPosition - 5000) <= 0) Then
       player.Seek(0)

   Else
       player.Seek(currentPosition - 5000)

   End If

End Sub

Private Sub Button_SeekForward_Click(sender As Object, e As EventArgs) Handles Button_SeekForward.Click

   Dim currentPosition As Long = CLng(player.Position.TotalMilliseconds)

   If Not ((currentPosition + 5000) >= player.Length) Then
       player.Seek(currentPosition + 5000)
   End If

End Sub

Sub Button_UnloadFile_Click() Handles Button_UnloadFile.Click

   If player.IsFileLoaded Then
       player.UnLoadFile()
   End If

End Sub


Saludos








Tazmania40

#2
Buenos días, en primer lugar muchas gracias Elektro, eres todo un genio. Si funciona el formato URI en el control WMP. La verdad estoy un poco perdido en tema de ficheros, pero veo que es la solución a los formatos de audio que no son WAV.

Visual Basic 2013 al añadir cualquier formato que no sea WAV toma como fichero como bien dices en My.Resources, pero ya veo una forma de poder utilizarlos y asi compilar un único archivo. Comentarte que lo que estoy realizando no es un Reproductor, sino un juego de naves y globos con dosis educativa (operaciones matemáticas para niños), donde tenía una música de fondo con WMP y utilizaba sonidos WAV con My.Computer.Audio.Play, que solo me dejaba reproducir uno a la vez. De esta forma podía combinar más sonidos puesto que el WMP puedes añadir más (realmente con el sonido de fondo y 2 sonidos más a la vez, disparo de nave y explosión me basta para no saturar, no empleo nada de DirectX y tampoco sé).

Respecto a tu código he añadido una línea para cambiar la extensión, puesto que el archivo temporal que te crea al reproducir te salta un mensaje que es una extensión .TMP y tienes que contestar y naturalmente eso no quiero que salga en el programa cada vez que reproduce el sonido o aunque sea 1 sola vez marcando el Checkbox.

Código (vbnet) [Seleccionar]

Dim filepath As String = Path.GetTempFileName()
filepath = Path.ChangeExtension(filepath, ".mid")
Dim fileUri As New Uri(String.Format("file:///{0}", filepath))
ExtractResourceToDisk(My.Resources.Sonido, filepath, overwrite:=True)

AxWindowsMediaPlayer1.URL = fileUri.AbsoluteUri


He probado con archivo MID (son los que utilizaré puesto que apenas ocupan), MP3 y archivos WAV (hay que quitarles extensión al añadir a My.Resources para que te lo añada como archivo) y funcionan todos perfectamente.

Implementaré esto en el código de mi juego y tan solo sera ver si no demora con el funcionamiento, puesto que antes solo utilizaba estas instrucciones para llamar a los sonidos

Código (vbnet) [Seleccionar]

My.Computer.Audio.Play(My.Resources.Sonido1, AudioPlayMode.Background)
AxWindowsMediaPlayer1.URL = "Sonido.mid"


En el código además de la nave, muevo unos cuantos objetos, Globos, disparos, fondo con un pequeño Scroll horizontal y comprobare que no se pare, aunque hoy día los ordenadores son muy rápidos, pero estoy utilizando Net.Framework 3.5 para que otros ordenadores más lentos y con XP también sea compatible.

Gracias por tu librería y muy currada. Yo soy un simple aficionado que más bien programo por hobby. Los programas y juegos que realizó intento que sean en un único archivo (utilizando las NET que ya tiene los ordeandores instalado). En este proyecto me será imposible porque Windows Media Player trae consigo dos librerías (AxInterop.WMPLib.dll e Interop.WMPLib.dll) aunque apenas ocupan, pero ya por lo menos todos los sonidos los tendré compilados con el ejecutable.

Sino es mucha molestia, pero a modo consulta no hace falta que me pongas código, con Windows Presentation Foundation (WPF) puesto que dicen que es más visual, que incluye animaciones, video, sonidos, 3D; se podría añadir recursos de audio que no sean WAV, en My.Resources o bien lo que tenga. Desconozco completamente WPF y cuando instale VB.net ya adapté el entorno a la programación con Windows Forms, puesto que yo venía de VB6.

Muchas gracias
Saludos


Eleкtro

#3
Cita de: Tazmania40 en 28 Mayo 2016, 12:22 PMcon Windows Presentation Foundation (WPF) se podría añadir recursos de audio que no sean WAV, en My.Resources

El administrador de recursos de WPF puede identificar los mismos tipos de archivo que para WinForms:



Pero como ya he explicado, puedes añadir cualquier tipo de archivo y leerlo.

En WPF puedes utilizar la class MediaPlayer, aunque no he comprobado si funciona con archivos MIDI:

Código (vbnet) [Seleccionar]
Dim fileUri As New Uri("file:///C:\Archivo.mid")
Dim player = New MediaPlayer()
player.Open(uri)
player.Play()


Ten en cuenta que puedes referenciar los ensamblados de WPF en tu proyecto WinForms para utilizar cualquier class de WPF, no es necesario migrar de tecnología.




Cita de: Tazmania40 en 28 Mayo 2016, 12:22 PMEn este proyecto me será imposible porque Windows Media Player trae consigo dos librerías (AxInterop.WMPLib.dll e Interop.WMPLib.dll) aunque apenas ocupan, pero ya por lo menos todos los sonidos los tendré compilados con el ejecutable.

WMP es un componente multimedia bastante "pesado" para lo que quieres hacer, si tener un código liviano es lo que quieres lograr, entonces yo te insisto en implementar la API de MCI para reproducir sonidos de fondo (varios al mismo tiempo).

Solo necesitas declarar esta función Win32:
Cita de: https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Interop/Win32/NativeMethods/NativeMethods_Audio.vb
Código (vbnet) [Seleccionar]
<SuppressUnmanagedCodeSecurity>
<DllImport("winmm.dll", EntryPoint:="mciSendString", SetLastError:=True,
                       CharSet:=CharSet.Auto, BestFitMapping:=False, ThrowOnUnmappableChar:=True)>
Public Shared Function MciSendString(ByVal command As String,
                                    ByVal buffer As StringBuilder,
                                    ByVal bufferSize As Integer,
                                    ByVal hwndCallback As IntPtr
) As Integer
End Function

Llamar a la función de la siguiente manera para cargar y reproducir archivos MIDI:
Cita de: https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Multimedia/Types/AudioPlayer.vb
Código (vbnet) [Seleccionar]
Dim filepath As String = "C:\Archivo.mid"'
Dim alias As String = "midi_1"
MciSendString(String.Format("open sequencer! ""{0}"" alias {1}", filepath, alias), Nothing, 0, IntPtr.Zero)
MciSendString(String.Format("play {0} from 0", alias), Nothing, 0, IntPtr.Zero)

Y liberar los recursos no-administrados cuando ya no necesites reproducir:
Cita de: https://github.com/ElektroStudios/ElektroKit/blob/master/Solution/Elektro.Interop/Win32/NativeMethods/NativeMethods_Audio.vb
Código (vbnet) [Seleccionar]
MciSendString(String.Format("stop {0}", alias), Nothing, 0, IntPtr.Zero)
MciSendString(String.Format("close {0}", alias), Nothing, 0, IntPtr.Zero)

Aquí tienes la documentación:

PD: También podrías copiar y pegar en tu código fuente una implementación ya hecha como por ejemplo la mía, no es necesario usar y/o distribuir mis dlls, puedes extraer esa parte del código y compilarla bajo .NetFx 3.5.

Saludos








Tazmania40

Muchas gracias de nuevo Elektro, un post tuyo da muchos temas que mirar sobre todo cuando llevas 1 año con el cambio de vb6 a vb2013, aunque eso está bien siempre hay que ver varias formas para aplicar un mismo resultado.

Estuve probando Windows Media Player en un equipo con XP y lamento decirte que el código que me proporcionastes no me funciona y en cambio de esta forma

Código (vbnet) [Seleccionar]

AxWindowsMediaPlayer1.URL = "C:\Temp\Sonido1.wav"


no hay problemas y se escucha la canción de fondo bien. Me dirás que soy un nostálgico y la verdad que viendo también que la nave que muevo (al usar la tecnica del doble buffer) se aprecia con el WXP y en W7 va fluido, aunque aqui posiblemente puede ser el equipo (es un P4 a 3 GHz con 3 Gb RAM), en otros que tengo Core2 (4 Gb RAM) e I5 (6 Gb RAM) va bien aunque tienen W7 de 32 y 64 bits. Puede que ya me plantee en dejar de utilizar Net Framework 3.5 y me pase al 4.5 por lo menos en los programas donde utilice graficos o sonido. Lo que pasa que mucha gente todavía tiene WXP, pero habrá que actualizarse.

El componente WMP aunque sea pesado las librerías principales las lleva Windows y aunque deja esas 2 librerias que no ocupan casi nada y como te he comentado no da problemas, para una canción de fondo y un sonido wav aparte va bien.

Auque ya empiezo a ver las limitaciones cuando ya empiezas a mover varios objetos, colocar imagenes de fondo que se mueven, utilizar varios sonidos y también me planteo mirar algo e ir al hardware. La verdad que estoy muy perdido y me gustaria seguir con vb.net. Aunque ahora es muy versatil la programación con Visual Studio y se ve con más facilidad para pasar de un lenguaje a otro. Mire que Visual c# podía utilizar las XNA Game Studio, pero estas han dejado de dar soporte Microsoft para las nuevas versiones de Visual Studio. El problema de DirectX es que la gente se tiene que bajar las librerias con Windows 7 (no se si van implentadas para versiones superiores, como NET Framework) y ocupan lo suyo y cuando publicas un programa he visto que si ocupa poco (se lo bajan mucho aunque sea peor) pero si ocupa y encima se tiene que bajar las librerías pues ya desisten.

Muchas gracias de nuevo, lo más probable que cuando acabe este proyecto para el próximo parecido utilice ya NET Framework 4.5 y descarte Windows XP.

Un saludo