Autor Tema: Ejemplo de como usar el Bass.dll  (Leído 2864 veces)

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

E N T E R

  • Petabyte
  • ******
  • Mensajes: 1062
  • Reputación: +57/-13
  • www.enterpy.com
    • Ver Perfil
    • www.enterpy.com
Ejemplo de como usar el Bass.dll
« en: Noviembre 12, 2014, 10:20:27 pm »
Hola, alguien tiene un ejemplo de como utilizar el Bass.dll, Esta DLL es para reproducir audio MP3 y varios mas, en su pagina web hay varios ejemplo pero son muy complicados para entender.

Lo que quiero hacer es:

1- Poder elegir en que tarjeta de sonido tocar el audio (por si la pc tiene mas de una tarjeta de sonido.)
2- Mostar un Vumeter.
3- Mostrar en un label el tiempo de reproduccion y lo que falta para terminar.

CIBER GOOGLE - CONCEPCIÓN PARAGUAY
www.enterpy.com
Primera regla de la programacion, para que vas a hacerlo complicado si lo puedes hacer sencillo

LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1128
  • Reputación: +151/-8
    • Ver Perfil
Re:Ejemplo de como usar el Bass.dll
« Respuesta #1 en: Noviembre 13, 2014, 12:51:06 am »
Hola Enter mira te puedo dar una ayuda rapida en base a lo que estoy haciendo, yo en realidad cree un modulo clase como para simplificar un poco las cosas, este modulo clase incluye otro modulo clase que es un timer asi que te paso los dos

ClsPlayAudio
Código: (Vb) [Seleccionar]
Option Explicit

Private m_FilePath As String
Private m_ChannelLength As Double
Private chan As Long
Private m_Pause As Boolean
Private WithEvents cTimer As ClsTimer
Private WithEvents cTimerRewindAdvance As ClsTimer
Public Event Progress(Percent As Long, ChannelPosition As Double)
Public Event EndAudio()
Private m_ChannelPosition As Double
Private m_Rewind As Boolean
Private m_Advance As Boolean
Private m_Repeat As Boolean
Private m_OldVolumen As Single
Private m_Mute As Boolean
Private m_OutDevice As Long


Public Function InitDevice(ByVal hwnd As Long, Optional device As Long = -1) As Boolean
    If (HiWord(BASS_GetVersion) <> BASSVERSION) Then Exit Function
    InitDevice = BASS_Init(device, 44100, 0, hwnd, 0) <> BASSFALSE
End Function

Public Property Get Mute() As Boolean
    Mute = m_Mute
End Property

Public Property Let Mute(value As Boolean)
    If value Then
        If m_Mute = False Then
            Call BASS_ChannelGetAttribute(chan, BASS_ATTRIB_VOL, m_OldVolumen)
            Call BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, 0)
            m_Mute = True
        End If
    Else
        If m_Mute Then
            Call BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, m_OldVolumen)
            m_Mute = False
        End If
    End If
End Property

 
Public Property Get Volumen() As Long
    Call BASS_ChannelGetAttribute(chan, BASS_ATTRIB_VOL, m_OldVolumen)
    Volumen = m_OldVolumen * 100
End Property

Public Property Let Volumen(value As Long)
    m_Mute = False
    m_OldVolumen = value / 100
    Call BASS_ChannelSetAttribute(chan, BASS_ATTRIB_VOL, m_OldVolumen)
End Property

Public Function LoadFile(sPath As String) As Boolean
    On Error GoTo ErrHandler
    If chan <> 0 Then Call BASS_StreamFree(chan)
   
    m_FilePath = vbNullString
   
    If Len(Dir(sPath, vbArchive)) = 0 Then Exit Function
   
    chan = BASS_StreamCreateFile(BASSFALSE, StrPtr(sPath), 0, 0, 0)

    If (chan = 0) Then GoTo ErrHandler
   
    m_FilePath = sPath
    m_Pause = True
    m_ChannelLength = BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetLength(chan, BASS_POS_BYTE))
    If m_OldVolumen > 0 Then Me.Volumen = m_OldVolumen * 100

    LoadFile = m_ChannelLength > 0
    Exit Function
ErrHandler:
    m_ChannelLength = 0
    Debug.Print "ClsPlayAudio Error LoadFile", sPath
End Function

Public Sub ReleaseFile()
    On Error Resume Next
    StopAudio
    If chan Then Call BASS_StreamFree(chan)
    m_ChannelLength = 0
    m_FilePath = vbNullString
    m_Mute = False
End Sub

Public Function Play() As Boolean
    If m_ChannelLength = 0 Then Exit Function
    m_Pause = False
    Play = BASS_ChannelPlay(chan, BASSFALSE)
    If Play Then
        cTimer.CreateTimer 100
    End If
End Function

Public Property Let device(ByVal OutDev As Long)
    Call BASS_ChannelSetDevice(chan, OutDev)
    m_OutDevice = OutDev
End Property

Public Property Get device() As Long
    device = m_OutDevice
End Property

Public Property Get AudioLength() As Double
    AudioLength = m_ChannelLength
End Property

Public Function StopAudio() As Boolean
    Me.Advance = False
    cTimer.DestroyTimer
    Call BASS_ChannelStop(chan)
    m_Pause = True
    BASS_ChannelSetPosition chan, BASS_ChannelSeconds2Bytes(chan, 0), BASS_POS_BYTE
    RaiseEvent Progress(0, 0)
   
End Function

Public Property Let Repeat(value As Boolean)
    m_Repeat = value
End Property

Public Property Get Repeat() As Boolean
    Repeat = m_Repeat
End Property


Public Property Let Pause(value As Boolean)
    If m_ChannelLength = 0 Then Exit Property
    If value Then
        Call BASS_ChannelPause(chan)
        cTimer.DestroyTimer
    Else
        Call BASS_ChannelPlay(chan, BASSFALSE)
        cTimer.CreateTimer 100
    End If
    m_Pause = value
End Property

Public Property Get Pause() As Boolean
    Pause = m_Pause
End Property

Public Property Get isAudioPlay() As Boolean
    isAudioPlay = BASS_ChannelIsActive(chan)
End Property

Public Property Get handle() As Long
    handle = chan
End Property

Public Property Get ChannelPosition() As Double
    ChannelPosition = BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE))
End Property

Public Property Let ChannelPosition(value As Double)
    BASS_ChannelSetPosition chan, BASS_ChannelSeconds2Bytes(chan, value), BASS_POS_BYTE
End Property

Public Property Let ChannelPositionPercent(value As Long)
    Dim lPercent As Long
    lPercent = m_ChannelLength * value / 100
    BASS_ChannelSetPosition chan, BASS_ChannelSeconds2Bytes(chan, lPercent), BASS_POS_BYTE
End Property

Public Property Get ChannelPositionPercent() As Long
    m_ChannelPosition = BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE))
    ChannelPositionPercent = m_ChannelPosition * 100 / m_ChannelLength
End Property

Public Property Let Advance(value As Boolean)
    m_Rewind = False
    m_Advance = value
    If value Then
        cTimerRewindAdvance.CreateTimer 500
    Else
        cTimerRewindAdvance.DestroyTimer
    End If
End Property

Public Property Get Advance() As Boolean
    Advance = m_Advance
End Property

Public Property Let Rewind(value As Boolean)
    m_Advance = False
    m_Rewind = value
    If value Then
        cTimerRewindAdvance.CreateTimer 500
    Else
        cTimerRewindAdvance.DestroyTimer
    End If
End Property

Public Property Get Rewind() As Boolean
    Rewind = m_Rewind
End Property



Private Sub Class_Initialize()
    m_OutDevice = -1 'Defaul
    Set cTimer = New ClsTimer
    Set cTimerRewindAdvance = New ClsTimer
End Sub

Private Sub cTimer_Timer(ByVal ThisTime As Long)

    Dim lPercent As Long
    If m_ChannelLength = 0 Then Exit Sub

    m_ChannelPosition = BASS_ChannelBytes2Seconds(chan, BASS_ChannelGetPosition(chan, BASS_POS_BYTE))

    lPercent = m_ChannelPosition * 100 / m_ChannelLength
    RaiseEvent Progress(lPercent, m_ChannelPosition)
   
   
    If BASS_ChannelIsActive(chan) = 0 Then
        Me.StopAudio
        If m_Repeat Then
            Me.Play
        Else
            RaiseEvent EndAudio
        End If
    End If
   
End Sub

Public Sub Forzar()
    Call BASS_ChannelStop(chan)
    Call BASS_StreamFree(chan)
End Sub

Private Sub Class_Terminate()
    Set cTimer = Nothing
    Set cTimerRewindAdvance = Nothing
    If chan Then Call BASS_StreamFree(chan)
    'Call BASS_Free  'esta deshabilitado porque si se usa mas de una clase corta el audio llamar BASS_Free al final de la aplicacion
End Sub

Private Sub cTimerRewindAdvance_Timer(ByVal ThisTime As Long)
    If m_Advance Then
        If Me.ChannelPosition >= m_ChannelLength Then
            Me.Advance = False
        Else
            Me.ChannelPosition = Me.ChannelPosition + 3
        End If
        Call cTimer_Timer(0)
    End If
   
    If m_Rewind Then
        If Me.ChannelPosition <= 0 Then
            Me.Rewind = False
        Else
            Me.ChannelPosition = Me.ChannelPosition - 3
        End If
        Call cTimer_Timer(0)
    End If
   
End Sub

ClsTimer
Código: (vb) [Seleccionar]
Option Explicit

Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

 ' Porcedur-Nummer der WndProc in der Klasse, wird zur Adressermittlung verwendet
Private Const ProcNr_WndProc = 0

Private Const GWL_WNDPROC As Long = -4

' Private Const asmMain As String = "558BEC83C4FC8D45FC50FF7514FF7510FF750CFF75086888888888B888888888FFD08B45FCC9C21000"
Private Const asmMain As String = "558BEC50FF7514FF7510FF750CFF75086855555555B866666666FFD0C9C21000"       '          |<pCls>|  |<Proc>|"
'                                                                    |<pCls>|  |<Proc>|
Private ASM() As Byte         ' Array für AsseblerCode

Private ProcPtr As Long
Private TimerID As Long       ' the TimerID which is returnd from the Windows SetTimer Function

' ===========================================================================
'  NAME: Timer
'  DESC: Timer-Event
'  PARA(ThisTime): Time in milli seconds since Windows start
' ===========================================================================

Event Timer(ByVal ThisTime As Long)

' ProcedureNr = 0
Public Sub TimerProc(ByVal hwnd As Long, _
              ByVal uMsg As Long, _
              ByVal idEvent As Long, _
              ByVal dwTime As Long)
' ===========================================================================
'  NAME: TimerProc
'  DESC: CallBack-Function for the Timer
'  DESC: Do not call this function by yourself, it's called from the
'  DESC: Windows Timer Function
'  DESC: This function must be public because we need the Procedure-Adress
'  DESC: for the Windows Call Back.
' ===========================================================================

   RaiseEvent Timer(dwTime)
End Sub

Public Function CreateTimer(ByVal Milliseconds As Long) As Long
' ===========================================================================
'  NAME: CreateTimer
'  DESC: Creates a Timer and returns a non zero Value which is the
'  DESC: Windows-Timer-ID when succeeding
'  DESC: It is not possible to change the interval, first kill the
'  DESC: Timer and create it new
' ===========================================================================
   Dim ret As Long
   
   If TimerID = 0 Then     ' If the Timer does not exist
      ' create the Timer
      ret = SetTimer(0&, 0&, Milliseconds, ProcPtr)
      If ret <> 0 Then
         TimerID = ret
         CreateTimer = ret
      End If
   Else                    ' if the Timer already exists
      ' pass back the current TimerID
      CreateTimer = TimerID
   End If

End Function

Public Function DestroyTimer() As Long
' ===========================================================================
'  NAME: DestroyTimer
'  DESC: Destroy the current Timer an pass back a non zero value when succeeding
' ===========================================================================
   Dim ret As Long
   
   If TimerID <> 0 Then       ' If the Timer exists
      ret = KillTimer(0&, TimerID)
      If ret <> 0 Then
         TimerID = 0
      End If
   End If
End Function

Private Function GetProcPtr(ClassPtr As Long, ProcNumber As Long) As Long
' ===========================================================================
'  NAME: GetProcPtr
'  DESC: eErmittelt anhand des ObjektPointers der Instanz und der laufenden
'  DESC: Procedure-Nummer der Klasse, die StartAdresse der Procedure/Function
'  PARA(ClassPtr As Long):    ObjektPointer der Instanz der Klasse
'  PARA(ProcNumber As Long):  Laufende Nr. der Procedure/Funktion (0-basierend)
'  RETURN:  StartAdresse der Procedure/Function
' ===========================================================================
   
   Dim ptrTemp As Long
   Dim ptrProc As Long
   
   ' ptrTemp = StartAdresse der Objektdefinitions-Daten = [ClassPtr]
   CopyMemory ptrTemp, ByVal ClassPtr, 4
   
   ' Die StartAdresse der Function in ptrProc kopieren
   ' &H1C ist die OffsetAdresse für die Procedureliste
   CopyMemory ptrProc, ByVal ptrTemp + &H1C + (4 * ProcNumber), 4
   
   GetProcPtr = ptrProc
End Function

Private Function CreateASMContainer(ClassPtr As Long, ProcNumber As Long) As Long
' ===========================================================================
'  NAME: CreateASMContainer
'  DESC: ByteArray mit AssemblerCode erstellen und ClassPtr und ProcPtr
'  DESC: in den AssemblerCode eintragen
'  PARA(ClassPtr):   ObjektPointer der Instanz von clsSubclass
'  PARA(ProcNumber): ProcedureNummer der WndProc in clsSubclass
'  Return: Startadresse der AssemblerRoutine (=Adresse 1 Byte im Array)
' ===========================================================================
   
   Dim ProcPtr As Long
   
   ProcPtr = GetProcPtr(ClassPtr, ProcNumber)

   
   Dim L As Long
   Dim W As Long
   L = Len(asmMain) \ 2 - 1
   
   ReDim ASM(0 To L)
   
   For W = 0 To L
     ASM(W) = "&H" & Mid$(asmMain, W * 2 + 1, 2)
   Next
   
   CopyMemory ASM(17), ClassPtr, 4     ' Objektadresse der Instanz in AssemblerCode eintragen
   CopyMemory ASM(22), ProcPtr, 4      ' Adresse der WndProc in AssemblerCode eintragen
   
   ' StartAdresse der AssemblerRoutine als Funktionswert zurückgeben
   CreateASMContainer = VarPtr(ASM(0)) ' StartAdresse der AssemblerRoutine als Funktionswert
End Function

Private Sub Class_Initialize()
   ProcPtr = CreateASMContainer(ObjPtr(Me), ProcNr_WndProc)
End Sub

Private Sub Class_Terminate()
   DestroyTimer
End Sub

y en un Formulario
Código: (Vb) [Seleccionar]
Option Explicit
Private WithEvents cPlayAudio1 As ClsPlayAudio

Private Sub cPlayAudio1_Progress(Percent As Long, ChannelPosition As Double)
    Dim Level As Long
    Dim BumetroL As Long
    Dim BumetroR As Long
   
    Me.Caption = Percent & " %"
    Level = BASS_ChannelGetLevel(cPlayAudio1.handle)
    If Level > -1 Then
        BumetroL = LoWord(Level) / 350
        BumetroR = HiWord(Level) / 350
        'ucBumetro1.Value = LoWord(Level) / 350
        'ucBumetro2.Value = HiWord(Level) / 350
       
        Me.Cls
        Me.Line (0, 150)-(Me.ScaleWidth * BumetroL / 100, 0), vbGreen, BF
        Me.Line (0, 350)-(Me.ScaleWidth * BumetroR / 100, 200), vbGreen, BF
       
    End If
End Sub

Private Sub Form_Load()
    Set cPlayAudio1 = New ClsPlayAudio
    cPlayAudio1.InitDevice Me.hwnd, 1
    cPlayAudio1.device = 1 'aca elegis la placa
   
    cPlayAudio1.LoadFile "D:\Mis documentos\Mi música\Bebel Gilberto\06 - Azul.mp3"
    cPlayAudio1.Play
End Sub

Private Sub Form_Unload(Cancel As Integer)
    cPlayAudio1.StopAudio
    Set cPlayAudio1 = Nothing
    Call BASS_Free
End Sub

bueno y obviamente tenes que incluir el modulo MdlBass.bas
una ves que pusiste a andar el ejemplo empeza a investigar la clase ClsPlayAudio y vas a ver que tiene unas cuantas funciones para reproducir audio.(pausa, stop play, adelantar revovinar, volumen .etc)

Aclaro la clase esta echa a mi necesidad puede que no ajuste a la necesidad de todos.

E N T E R

  • Petabyte
  • ******
  • Mensajes: 1062
  • Reputación: +57/-13
  • www.enterpy.com
    • Ver Perfil
    • www.enterpy.com
Re:Ejemplo de como usar el Bass.dll
« Respuesta #2 en: Noviembre 13, 2014, 01:52:42 pm »
Hola, Leandro estaba mirando tu codigo espectacular esta todo es mas facil y legible asi estaba toqueteando unas cosas y lo que no le pude poner es el tema del tiempo y la barra de progreso para poder adelantar y atrasar el audio.

LINK DEL EJEMPLO
https://mega.co.nz/#!FMckTRjQ!1nrpRnszHivrVeBy2wL_pZINiZL1hSq6Kx4WJCrMYCw
CIBER GOOGLE - CONCEPCIÓN PARAGUAY
www.enterpy.com
Primera regla de la programacion, para que vas a hacerlo complicado si lo puedes hacer sencillo