Oppure

Loading
05/02/21 22:14
iz1kbp
Buongiorno a tutti.
Ho una utility ,non mia, trovata nel web, che mi permette di estrarre l'inviluppo (forma d'onda) di un file wave.L'utility è molto vecchia ma funziona bene.Il mio problema è che ai tempi i file wave erano sostanzialmente nel formato cd (44100, 16bt, stereo).Ora purtroppo devo operare con file wave di formati differenti, ed in particolare con 48000, 16bt, stereo.
Ho trovato il modo di far leggere correttamente i due formati modificando questa sezione di codice che si trova nella sezione DICHIARAZIONI del form che fa il lavoro di estrazione.

Al posto di 882 metto 960
'----------------------------------------------------------
' 882 deriva da:
'   44100 = 1 secondo
'   441   = 1/100 secondi         > per 48Mhz :480
'   882   = 441 * 2 (2 = stereo)   > per 48MHz :960
'----------------------------------------------------------
Private Type WAVEBLOCK
    wavinfo(1 To 882) As Integer
End Type


Io riesco a leggere la frequenza di campionamento del file nel momento in cui lo carico e mi occorrerebbe, che il dato (882 nel caso sopra) possa essere modificato nel momento in cui carico il file wave.
Ho provato a mettere un IF nella mia sub che carica il file wave ma non fuziona.
Qualcuno mi sa indicare se è possibile eseguire la funzione sopra,non all'avvio del form come avviene ora,ma all'interno di un subroutine come ad esempio
If  samplerate = 44100 Then
            ...modifico in 882
            Label25.Caption = "44100"
        
        Else
            ...modifico in 960
            Label25.Caption = "48000"
        
    End If


Questo per pemettermi di caricare indistintamente file a 44100 e 48000 di sample rate.
Nella situazione attuale, per caricare uno o l'altro devo uscire dal programma, modficare il dato via codice e ripartire.
Spero di essermi spiegato in maniera comprensibile.

Grazie a chiunque possa illuminarmi

mario
;)
aaa
06/02/21 8:20
nessuno
Imposta nel codice due strutture diverse e usa quella che ti serve al momento
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità;) chiamava il gioco del Lotto Tassa sulla stupidità.
06/02/21 10:00
Carlo
quando carichi il file wave, lo devi analizzare, in base al responso metti in una variabile il valore voluto
in vb6 per analizzare il file puoi usare Shell32.dll:
pierotofy.it/pages/sorgenti/dettagli/19629-INFOfile=Shell32/
è in VB .Net ma il concetto è lo stesso.

Altra possibilità più semplice è mettere due OptionButton, uno che si chiama 44,1KHz e l'altro 48,0KHz quando l'optionbutton viene cliccato cambi il valore della variabile e richiami la routine che crea la forma d'onda.

Il codice con l'If che hai proposto, da solo non è sufficiente, non conosco le tue competenze in VB6, se hai difficoltà posta il codice completo.
in programmazione tutto è permesso
06/02/21 10:15
iz1kbp
Ciao Carlo, grazie per il replay.
LE mie conoscenze vb6 sono abbastanza "basiche". Il file wav riesco ad analizzarlo senza problemi, infatti la mia intenzione era, leggendo il sample rate, quella di automatizzare il dimensionamento di quel numero.
Questa è la parte di dichiarazione al boot del form
Option Explicit
Private riga As Integer
Dim wavtoshow As String
Dim play As Boolean
Dim a As Integer
Dim pos ' posizione cursore in edit
Dim edit
Dim lung As String
Dim accss As String
Dim Posizione As Long ' posizione del cursone nella grafica
Dim totale As Long ' totale lunghezza della linea nella grafica
Dim errore As Integer
Dim ritardo As Integer 'varibili per timer 2
Dim attendi As Integer 'variabili per  timer 2 attendoi  di arrivare a ritardo
Dim proseguo As Integer 'se rver per sapere se prosegue la cattura
Dim annullata As Integer 'procedura di carico wave annullata per evitare di inizilizzare griglia
Private Declare Function MoveToEx Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, lpPoint As Any) As Long
Private Declare Function LineTo Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function GetShortPathNameAPI Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
Private Const MAX_PATH As Long = 260
Private Type WAVEFMT
    signature As String * 4     ' must contain 'RIFF'
    RIFFsize As Long            ' size of file (in bytes) minus 8
    type As String * 4          ' must contain 'WAVE'
    fmtchunk As String * 4      ' must contain 'fmt ' (including blank)
    fmtsize As Long             ' size of format chunk, must be 16
    format As Integer           ' normally 1 (PCM)
    Channels As Integer         ' number of channels, 1=mono, 2=stereo
    samplerate As Long          ' sampling frequency: 11025, 22050 or 44100
    average_bps As Long         ' average bytes per second; samplerate * channels
    align As Integer            ' 1=byte aligned, 2=word aligned
    BitsPerSample As Integer    ' should be 8 or 16
    datchunk As String * 4      ' must contain 'data'
    samples As Long             ' number of samples
End Type
 
Private Type POINT
    X As Long
    Y As Long
End Type
 
'----------------------------------------------------------
' 882 comes from:
'   44100 = 1 second
'   441   = 1/100 second
'   882   = 441 * 2 (2 = stereo)
'----------------------------------------------------------
Private Type WAVEBLOCK
    'wavinfo(1 to 882) As Integer ----- 
wavinfo() as integer ' mia modifica per cercare di modificarlo al momento del caircamento del file wave
End Type
 
Private Type SCROLLER
    Min As Long
    Max As Long
    Value As Long
    topval As Long  'Position represented by top line of wavform
End Type

Dim nomefileaudio As String
Dim fil As String
Dim WavCount As Long, WavMin() As Integer, WavMax() As Integer
Dim ttt As WAVEBLOCK, LastPt As POINT, VScroll As SCROLLER
Dim WavSpeed As Integer
Dim delete As Boolean
' The column selected for sorting.
Private m_SortColumn As Integer
' The current sort order.
Private m_SortOrder As SortSettings
Dim cancellariga As Integer
Dim copia As Boolean
Dim voltemp As Integer
Dim prima, dopo As Integer 'nel caso di edit con S sono il dato prima e dopo la correzzione
'Dim finewavcount As Integer
Dim finewavcount As Long
Dim lunghezza As Integer
Dim nibblelf, nibblehf As Long
Dim nibblels, nibblehs As Long
Dim nibblelm, nibblehm As Long
Dim nibblelh, nibblehh As Long
Dim exframe, exsecondi, exminuti, exore, ll, hh As String


Quel valore che assume wave info (882) viene poi ripreso dalla variabile ttt.

questo il codice che mi carica il file wav
Dim t1 As Long, tmin As Integer, tmax As Integer
    Dim wavh As WAVEFMT
    
    With CM
        .FileName = vbNullString
        .InitDir = App.path & "\cartelle\WAV"
        .FileName = ""
        .Filter = "Audio Wav(*.wav)|*.wav"
        .ShowOpen
        fil = .FileName
        percorsomarcatori = .FileName
        If fil = "" Then
                        MsgBox "Annullata da utente"
                        annullata = 1
                        Exit Sub
        End If
        '------------------------------------------
        
        lung = Len(fil)
            Dim l1 As Integer
            Dim l2 As Integer
            For n = 1 To lung
                If Mid(fil, n, 4) = "\WAV" Then l1 = n + 5
                If Mid(fil, n, 1) = "." Then l2 = n
            Next
            If l1 = 0 Then
                        MsgBox "Importare il file WAVE tramite procedura", vbExclamation, "XLight IV - Importare file wave"
                        Close
                        errore = 1
                        Exit Sub
            End If
        accss = Mid(fil, l1, l2 - l1)
        wavtoshow = accss
        '----------------------------------------
        Me.Caption = "XLIGHT IV - " & accss
    End With
    Me.Refresh  'Do this to remove lingering dialog box lines
    If fil = "" Then Exit Sub
    If Dir(fil, vbNormal) = "" Then Exit Sub
    
    MP.FileName = fil
    MP.Stop
    '-----------------------------------------
    '  Only allow wavh.bitspersample = 16!!!
    '-----------------------------------------
    Open fil For Binary Access Read As #1
    Get #1, , wavh
'[b]-----mia modifica per cercare di impostare il valore in base al formato[/b]
    If wavh.samplerate = 44100 Then
         ReDim wavinfo(1 To 960) As Integer
     Else
        ReDim wavinfo(1 To 820) As Integer
    End If
 '[b]---------------------fine mia modifica [/b]  
    WavCount = wavh.samples \ Len(ttt)
    
    ReDim WavMin(WavCount), WavMax(WavCount)
    
    Screen.MousePointer = vbHourglass
'Dim extraaudio As Integer
    ProgressBar1.Max = WavCount
    finewavcount = WavCount
    ProgressBar1.Value = 0
    ProgressBar1.Visible = True
    
    WavCount = -1
    Do
        Get #1, , ttt

aaa
06/02/21 11:08
Carlo
Si, ma per agevolarmi il compito, allega uno zip con il progetto che funziona, per fare una cosa fatta bene bisogna implementare il 48000, che non è contamplato in:
samplerate As Long          ' sampling frequency: 11025, 22050 or 44100

metti anche la riga che ti fa funzionare il codice a 48000 remmata, e l'originale no.

in programmazione tutto è permesso
06/02/21 12:07
iz1kbp
Grazie Carlo.
Ti allego i file originali (waveplay.vbp) dato che nel programma che ho sviluppato, ho dovuto implementarlo modificandolo sostanzialmente per esigenze mie funzioni che necessitano di altri programmi esterni e/o periferiche che altrimenti andrebbero installate.
ma comunque la parte che interessa si vede gia in partenza.
Ho allegato anche due piccoli file wave , uno a 44khz ed uno a 48 khz.
Scopo di questo codice è caricare un file wave e rappresentare la sua forma d'onda (approssimata in mono) in un player.Quando si schiaccia play la forma d'onda scorre.la linea rossa rappresenta il campione che viene eseguito in quel momento.
A prima vista, senza modifiche di codice, i file vengono caricati senza problemi.
Cosa fare:
Con impostato 882 (default), carica il file test_44 e vedrai, facendo il play, che gli eventi sonori (sono dei semplici beep) partono esattamente appena intersecano la linea rossa.
carica successivamento il file test_48 e fai il play. Noterai che gli eventi sonori partiranno sempre piu in ritardo rispetto alla linea rossa.
Se cambi da 882 con 916, avrai il comportamento contrario.

Dato che da codice (waveh.samplerate) riesco a capire che tipo di codifica ha il file, all'atto del LOAD FILE, volevo che il numero 882 o 960 venisse messo in automatico in modo da poter caricare indifferentemente un file anziche l'altro.
Cosi come è adesso ,devo ogni volta ricompilare ed eseguire il programma e riesco a visualizzare correttamento solo un tipo di file
aaa
06/02/21 18:38
Carlo
La matrice wavinfo fa parte della variabile definita come tipo WAVEBLOCK, che poi viene assegnata alla variabile ttt.
Tali designazioni pubbliche avvengono in fase di dichiarazione, per cui se ridimensioni la matrice waveinfo in runtime, la modifica non si riperquoterà in ttt
Ritengo che ci sia un metodo per ottenere quanto da te richiesto, ma ammetto che in VB6 non mi è mai capitato di doverlo fare, anche perché la doppia designazione è inutile, è sufficiente dichiarare solo ttt.
Il codice seguente funziona, ma è gradita la conferma.

ATTENZIONE nel codice le righe:
' TimeDisplay.SetVal 0, 0, WavCount 'Parameters: value, min, max
' TimeDisplay.SetVal VScroll.value
le ho remmate perché nel mio VB6 l'user control non funziona e non ho impiegato tempo per capire perché

Option Explicit

Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, lpPoint As Any) As Long
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

Private Type WAVEFMT
    signature As String * 4     ' must contain 'RIFF'
    RIFFsize As Long            ' size of file (in bytes) minus 8
    type As String * 4          ' must contain 'WAVE'
    fmtchunk As String * 4      ' must contain 'fmt ' (including blank)
    fmtsize As Long             ' size of format chunk, must be 16
    format As Integer           ' normally 1 (PCM)
    channels As Integer         ' number of channels, 1=mono, 2=stereo
    samplerate As Long          ' sampling frequency: 11025, 22050 or 44100
    average_bps As Long         ' average bytes per second; samplerate * channels
    align As Integer            ' 1=byte aligned, 2=word aligned
    bitspersample As Integer    ' should be 8 or 16
    datchunk As String * 4      ' must contain 'data'
    samples As Long             ' number of samples
End Type
 
Private Type POINT
    x As Long
    y As Long
End Type
 
'----------------------------------------------------------
' 882 comes from:
'   44100 = 1 second
'   441   = 1/100 second
'   882   = 441 * 2 (2 = stereo)
'----------------------------------------------------------
' eliminata dichiarazione tipo WAVEBLOCKS

Private Type SCROLLER
    min As Long
    max As Long
    value As Long
    topval As Long  'Position represented by top line of wavform
End Type
 
Dim Fil As String
Dim WavCount As Long, WavMin() As Integer, WavMax() As Integer
Dim ttt() As Integer ' ttt può essere direttamente la matrice ridimensionabile
Dim LastPt As POINT
Dim VScroll As SCROLLER
Dim WavSpeed As Integer

Private Sub cmdOpen_Click()
    LoadWaveForm
End Sub

Private Sub Command1_Click()
    MP.CurrentPosition = MP.CurrentPosition + 0.01
End Sub

Private Sub Form_Load()
    LabStatus = ""
    WavSpeed = 50   'Default value for Speed Change button
    SlideSpeed.value = 100
    SlideVolume.value = 100
    SlideBalance.value = 0
End Sub

Private Sub Form_Unload(Cancel As Integer)
    MP.FileName = ""
End Sub


Private Sub PicWave_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
    MP.CurrentPosition = (VScroll.topval + x) / 100
    VScroll.value = VScroll.topval + x
End Sub

Private Sub LoadWaveForm()
    Dim t1 As Long, tmin As Integer, tmax As Integer
    Dim wavh As WAVEFMT
    
    With CM
        .FileName = ""
        .Filter = "Wav(*.wav)|*.wav"
        .ShowOpen
        Fil = .FileName
    End With
    Me.Refresh  'Do this to remove lingering dialog box lines
    If Fil = "" Then Exit Sub
    If Dir(Fil, vbNormal) = "" Then Exit Sub
    
    MP.FileName = Fil

    '-----------------------------------------
    '  Only allow wavh.bitspersample = 16!!!
    '-----------------------------------------
    Open Fil For Binary Access Read As #1
    Get #1, , wavh
    frmMain.Caption = wavh.samplerate
    If wavh.samplerate = 44100 Then
        ReDim ttt(1 To 882) As Integer
    Else
        ReDim ttt(1 To 960) As Integer
    End If
    
    WavCount = wavh.samples \ UBound(ttt)
    ReDim WavMin(WavCount), WavMax(WavCount)
    
    Screen.MousePointer = vbHourglass

    ProgressBar1.max = WavCount
    ProgressBar1.value = 0
    ProgressBar1.Visible = True
    
    WavCount = -1
    Do
        Get #1, , ttt
        'Find min/max to get a better view of the wave
        tmin = 0: tmax = 0
        'Should look at all values but 'Step 32' speeds it up a bit
        'A nice C++ function to find the max/min would be handy here!
        For t1 = 1 To UBound(ttt) Step 32
            tmin = IIf(ttt(t1) < tmin, ttt(t1), tmin)
            tmax = IIf(ttt(t1) > tmax, ttt(t1), tmax)
        Next t1
        WavCount = WavCount + 1
        WavMin(WavCount) = tmin \ 512 + 64  'Long values become +/-64 then
        WavMax(WavCount) = tmax \ 512 + 64  'add 64 to make into co-ordinates
        
        If WavCount Mod 100 = 0 Then ProgressBar1.value = WavCount
    Loop Until EOF(1)
        
    Close #1
    ProgressBar1.Visible = False
    ProgressBar1.value = 0

    VScroll.min = 0
    VScroll.max = WavCount
    VScroll.value = 0
            
   ' TimeDisplay.SetVal 0, 0, WavCount   'Parameters: value, min, max
    
    DrawWaveData
    Screen.MousePointer = vbDefault
End Sub

Private Sub PlaySpeed_Click()
    SlideSpeed.value = IIf(SlideSpeed.value = 100, WavSpeed, 100)
End Sub

Private Sub SlideBalance_Change()
    MP.Balance = SlideBalance.value * 100   'Balance is +/- 10000
End Sub

Private Sub SlideBalance_Scroll()
    SlideBalance_Change
End Sub

Private Sub SlideSpeed_Change()
    If SlideSpeed.value <> 100 Then WavSpeed = SlideSpeed.value
    frameSpeed.Caption = "Speed:" & SlideSpeed.value & "%"
End Sub

Private Sub SlideSpeed_Scroll()
    SlideSpeed_Change
End Sub

Private Sub SlideVolume_Change()
    frameVolume.Caption = "Volume:" & SlideVolume.value & "%"
End Sub

Private Sub SlideVolume_Scroll()
    SlideVolume_Change
End Sub

Private Sub TimeDisplay_Change(newPacks As Long)
    MP.CurrentPosition = newPacks / 100
End Sub

Private Sub Timer1_Timer()
    Dim mpos As Long, mvol As Long
    If MP.Rate <> SlideSpeed.value / 100 Then MP.Rate = SlideSpeed.value / 100
    
    mvol = -(100 - SlideVolume.value) * 100     'Media Player volume = 0 (max) to -10000 (min)
    If MP.Volume <> mvol Then MP.Volume = mvol
    
    mpos = Int(MP.CurrentPosition * 100)
    If mpos >= VScroll.min And mpos <= VScroll.max And VScroll.value <> mpos Then
        VScroll.value = mpos
        DrawWaveData
    End If
End Sub


'-------------------------------------------------
' Main drawing routine
'-------------------------------------------------
' MoveToEx and LineTo are GDI functions, many
' times faster than their VB equivalents and
' just as easy to use
'
' Picture containing the wave form is 400 wide
' so change this code to suit your needs
'-------------------------------------------------
Sub DrawWaveData()
    Dim t1 As Long, vstart As Long, hline As Integer
    vstart = VScroll.value
    
    'Make sure the cursor starts at the left, moves to the middle,
    'then the waveform moves until at the end the cursor moves right
    If vstart < 200 Or WavCount < 400 Then      'First 200
        hline = vstart
        vstart = 0
    ElseIf vstart > WavCount - 200 Then         'Last 200
        hline = vstart - WavCount + 400
        vstart = WavCount - 400
    Else                                        'Anything else
        hline = 200
        vstart = vstart - 200
    End If
    VScroll.topval = vstart
    
    PicWave.Cls
    PicWave.ForeColor = vbGreen
    
    'Draw each line
    For t1 = 0 To IIf(WavCount < 400, WavCount, 400)
        MoveToEx PicWave.hdc, t1, WavMin(vstart + t1), LastPt
        LineTo PicWave.hdc, t1, WavMax(vstart + t1)
        
        'Marks for 0.1 (small) and 1-second (large) intervals
        If (vstart + t1) Mod 10 = 0 Then
            MoveToEx PicWave.hdc, t1, 128, LastPt
            LineTo PicWave.hdc, t1, IIf((vstart + t1) Mod 100 = 0, 100, 120)
        End If
    Next t1
    
    MoveToEx PicWave.hdc, 0, 64, LastPt 'Draw center line
    LineTo PicWave.hdc, 400, 64
    
    PicWave.ForeColor = vbRed           'Draw cursor line
    MoveToEx PicWave.hdc, hline, 0, LastPt
    LineTo PicWave.hdc, hline, 500
    
    PicWave.Refresh
    
    LabStatus.Caption = VScroll.value & " of " & WavCount & " (" & WavCount / 100 & " seconds)"
   ' TimeDisplay.SetVal VScroll.value
End Sub

Ho controllato solo la sincronia... :heehee:
:k:
Ultima modifica effettuata da Carlo 07/02/21 7:54
in programmazione tutto è permesso
06/02/21 19:33
iz1kbp
Grande Carlo,funziona regolarmente!!
Si, avevo capito il discorso della doppia assegnazione ma non riuscivo a capire, perchè non l'ho mai usato,il discorso dell'aggiornamento dinamico di una variabile e non dell'altra.
Certe finezze cognitive sono molto sopra il mio livello di conoscenze in vb6.:hail:
Ti ringrazio per l'aiuto e per la spiegazione.
A presto e grazie ancora.

Mario

:k:
aaa