Differenze tra le versioni di "Conoscere la durata di un file Midi con le sole risorse di Gambas"

Da Gambas-it.org - Wikipedia.
 
(42 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Per conoscere la durata di un file Midi mediante le sole risorse di Gambas, è possibile utilizzare un codice come il seguente, nel quale si otterranno anche le durate delle singole tracce ''MTrk'' presenti nel file ed alcune generiche informazioni:  
+
Il procedimento, seguito per ottenere la durata in secondi di un file Midi deve tenere in debita considerazione la circostanza che all'interno di un brano musicale possono insistere una o più variazioni del ''tempo metronomico''. La durata del file Midi rappresenta così la somma delle singole durate determinate dagli eventuali cambi del ''tempo metronomico'' all'interno del file Midi.
 +
 
 +
Ciò richiede innanzitutto la conoscenza dei seguenti elementi:
 +
* ''tempo metronomico'': movimenti (battute) per minuto (bpm), che si otterrà a sua volta dallo specifico Meta-evento FF 51;
 +
* ''tick reali'' dell'intera traccia Midi più grande, ossia la quantità di ''tick'' ottenuti dalle somme dei ''Tempi Delta'' (quest'ultimi convertiti ciascuno dal proprio formato ''a lunghezza variabile'', nel quale sono espressi nel file Midi) fra ogni evento Midi e quello immediatamente successivo;
 +
* ''risoluzione del Tempo Delta'' (TΔ), espressa in ordine ''Big-Endian'' nel 13° e nel 14° byte del file Midi.
 +
 
 +
Pertanto, per ciascun "tratto" parziale di durata devono essere ottenuti il ''tempo metronomico'' (bpm), leggendolo dall'apposito Meta-evento FF 51, e i ''tick'' reali. Da tali elementi, considerando anche la risoluzione del ''Tempo Delta'' (TΔ), si otterrà per ogni "tratto" la durata in secondi, adottando la seguente formula:
 +
((60 / bpm) / risoluzione_TΔ) * tick_reali = secondi
 +
Successivamente bisogna ricavare anche il ''tempo metronomico'' e la quantità di ''tick'' reali maggiore fra le tracce (MTrk), e da questi due elementi, unitamente alla costante risoluzione del ''Tempo Delta'', si otterrà la durata in secondi del "tratto finale" (per "tratto finale" qui intendiamo la quantità di ''Tempo Delta'' compresa fra l'ultimo Meta-evento FF 51 e il Meta-evento di chiusura FF 2F 00 della traccia avente la quantità maggiore di tick rispetto alle altre).
 +
 
 +
In ogni caso va ricordato che il valore <SPAN Style="text-decoration:underline">predefinito</span> del ''tempo metronomico'' è pari a 120 bpm.
 +
 
 +
Si potrà avere dunque, ad esempio, una situazione di questo genere:
 +
0------FF51--------FF51----------FF51--------------FF2F00  (Traccia Midi di maggiore durata)
 +
| 120        bmp1        bmp2  |        bmp3    |
 +
|______|___________|_____________|_________________|
 +
      tratto iniziale durata        tratto finale
 +
|__________________________________________________|
 +
            Durata totale del file Midi
 +
In altri termini si procederà a:
 +
 
 +
1) estrarre il numero dei ''tick'' reali compresi fra l'inizio assoluto delle tracce Midi (punto TΔ = 0) e l'ulimo Meta-evento FF 51, ossia fino all'ultimo ''Tempo Delta'' precedente l'ultimo Meta-evento FF 51): "1° tratto" della durata del file Midi. Questo andrà ottenuto estraendo i ''tick'' reali per <SPAN Style="text-decoration:underline">ogni tratto</span> compreso tra i vari Meta-eventi FF 51 del "1° tratto".
 +
 
 +
2) estrarre il numero dei ''tick'' reali <SPAN Style="text-decoration:underline">più grande</span> fra le tracce esistenti del file Midi. Ciò significa che si dovrà ottenere il numero di ''tick'' reali della traccia che dura di più.
 +
 
 +
3) ottenere i ''tick'' reali del "tratto finale" più lungo fra le tracce esistenti, sottraendo i ''tick'' reali del "tratto iniziale" (punto 1) ai ''tick'' reali della traccia più duratura (punto 2).
 +
 
 +
4) convertire in secondi separatamente i ''tick'' reali di ciascun tratto costituente il "tratto iniziale".
 +
 
 +
5) convertire in secondi i ''tick'' reali del "tratto finale".
 +
 
 +
6) sommare i valori temporali, espressi in secondi, dei singoli tratti (punto 4) costituenti il "tratto iniziale" della durata del file Midi.
 +
 
 +
 
 +
Esempio pratico:
 +
<BR>a) 77959 ''tick'' reali della traccia più duratura;
 +
<BR>b) 52992 ''tick'' reali del "tratto iniziale";
 +
<BR>c) 77952 - 52992 = 24960 ''tick'' reali del "tratto finale" più lungo fra le tracce esistenti;
 +
<BR>d) conversione in secondi di ciascun singolo tratto costituente il "tratto iniziale" della durata del file Midi;
 +
<BR>e) secondi_tratto_iniziale + secondi_tratto_finale = durata effettiva del file Midi
 +
 
 +
 
 +
Dunque, per conoscere la durata di un file Midi mediante le sole risorse di Gambas, è possibile utilizzare un codice come il seguente, nel quale si otterranno anche le durate delle singole tracce ''MTrk'' presenti nel file ed alcune generiche informazioni:  
  
Private fl As File
 
Private file_offset As Integer
 
Private bpm$ As String
 
 
 
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
    
 
    
 +
  Dim fl As File
 
   Dim fileMidi, s As String
 
   Dim fileMidi, s As String
   Dim durata_Midi As Float
+
   Dim hbpm, tot, mx, tratto1 As Integer
 +
  Dim td, bpm, c As Short
 +
  Dim tr, b, n, av As Byte
 +
  Dim cmd, tipocmd, ultimo As Byte
 +
  Dim f, durata As Float
 
    
 
    
  fileMidi = "''/percorso/del/file.mid''"
+
  fileMidi = "<FONT Color=gray>''/percorso/del/file.mid''</font>"
  Print "File Midi:";; fileMidi
+
  Print "File Midi:         "; fileMidi
  Print "Dimensione:";; Stat(fileMidi).Size;; "byte"
+
 
 
+
  fl = Open fileMidi For Read
  fl = Open fileMidi For Read
+
  If IsNull(fl) Then Error.Raise("Impossibile aprire il file !")
  If IsNull(fl) Then Error.Raise("Impossibile aprire il file !")
+
 
   
+
  Read #fl, s, 4
  Read #fl, s, 4
+
  If s <> "MThd" Then Error.Raise("Il file non è uno standard Midi !")
  If s <> "MThd" Then Error.Raise("Il file non è uno standard Midi !")
+
  Print "Dimensione:    "; Lof(fl); " byte"
   
+
  Seek #fl, 9
  durata_Midi = legge_smf()
+
  Read #fl, c
   
+
  Print "Tipo file:        "; c
  Print "\n\n  DURATA del FILE MIDI:  "; Date(0, 0, 0, 0, 0, 0, durata_Midi * 1000)
+
  Read #fl, tr
   
+
  Print "Numero tracce:  "; Format(tr, "###")
 +
  Read #fl, td
 +
  td = Rol(td, 8)
 +
  Print "Risoluzione TΔ:  "; Format(td, "###")
 +
  Avanza(fl, 8)
 +
 
 +
  bpm = 120
 +
 
 +
  Repeat
 +
    tot = 0
 +
    Do
 +
      tot += legge_var(fl)
 +
      Read #fl, b
 +
      If b And 128 Then  <FONT Color=gray>' ''Status running''</font>
 +
        cmd = b
 +
        If b < &F1 Then ultimo = cmd
 +
        av = 2
 +
      Else
 +
        cmd = ultimo
 +
        av = 1
 +
      Endif
 +
      tipocmd = Shr(cmd, 4)
 +
      Select Case tipocmd
 +
        Case 8 To 11
 +
          Avanza(fl, av)
 +
        Case 12 To 13
 +
          Avanza(fl, 1)
 +
        Case 14
 +
          Avanza(fl, av)
 +
        Case 15
 +
          If b = &F0 Then          <FONT Color=gray>' ''Evento SysEx''</font>
 +
            Repeat
 +
              b = Read #fl As Byte
 +
            Until b = &F7
 +
          Else
 +
            Read #fl, b
 +
            Select Case b
 +
              Case &51
 +
                durata += DurataParziale(bpm, td, tot)
 +
                tratto1 += tot
 +
                tot = 0
 +
                Avanza(fl, 1)
 +
                hbpm = 0
 +
                For c = 2 To 0 Step -1
 +
                  Read #fl, n
 +
                  hbpm += Shl(CInt(n), 8 * c)
 +
                Next
 +
                bpm = 60000000 / hbpm
 +
              Case &2F
 +
                mx = Max(mx, tot)
 +
                Exit
 +
              Case Else
 +
                Read #fl, b
 +
                Avanza(fl, b)
 +
            End Select
 +
          Endif
 +
      End Select
 +
    Loop
 +
    Dec tr
 +
    If tr > 0 Then Avanza(fl, 9)
 +
  Until tr = 0
 +
 
 +
  fl.Close
 +
 
 +
  f = DurataParziale(bpm, td, Max(mx, tratto1) - tratto1)
 +
 
 +
  Print "\nDURATA:      \e[31m\e[1m"; CStr(Time(0, 0, 0, (f + durata) * 1000)); "\e[0m"
 +
 
 
  '''End'''
 
  '''End'''
 
 
'''Private''' Function legge_smf() As Float  <FONT Color=gray>' ''Legge l'intero file Midi''</font>
 
 
    
 
    
   Dim lung_MThd, tipo, risoluzione_TD, lenI As Integer
+
    
  Dim num_tracce As Short
+
'''Private''' Procedure Avanza(mf As File, av As Byte)
  Dim err, traccia As Byte
+
    
   Dim s As String
+
   Dim b, n As Byte
   Dim dur, superior As Float
 
 
<FONT Color=gray>' ''La corrente posizione all'interno del file è immediatamente dopo "Mthd":''</font>
 
  lung_MThd = legge_dal_file(4)
 
  If lung_MThd <> 6 Then Error.Raise("Formato di file non valido !")
 
 
 
  tipo = legge_dal_file(2)
 
  If (tipo <> 0) And (tipo <> 1) Then Error.Raise("Il tipo " & tipo & " non è supportato !")
 
  Print "Tipo file Midi:";; tipo
 
 
    
 
    
  num_tracce = legge_dal_file(2)
+
  For b = 1 To av
  If (num_tracce < 1) Or (num_tracce > 1000) Then Error.Raise(num_tracce & ": è un numero di tracce non valido !")
+
    Read #mf, n
  Print "Numero totale Tracce:";; num_tracce
+
  Next
 
 
  risoluzione_TD = legge_dal_file(2)
 
  If risoluzione_TD < 0 Then Error.Raise("Formato di file non valido !")
 
  Print "Risoluzione Tempo Delta:";; risoluzione_TD
 
 
  Print "\n\n=== DURATA delle";; num_tracce;; "TRACCE ===\n"
 
 
 
<FONT Color=gray>' ''Legge le tracce MTrk del file Midi:''</font>
 
  For traccia = 1 To num_tracce
 
<FONT Color=gray>' ''Cerca il blocco "Mtrk" della traccia corrente:''</font>
 
    For err = 0 To 1
 
      Read #fl, s, 4
 
      lenI = legge_dal_file(4)
 
      If Eof(fl) Then Error.Raise("Inattesa fine del file !")
 
      If (lenI < 0) Or (lenI >= 268435456) Then Error.Raise(CStr(lenI) & ": lunghezza del blocco traccia non valido !")
 
      If s = "MTrk" Then Exit
 
    Next
 
   
 
    file_offset = Seek(fl)
 
     
 
    dur = legge_traccia(CStr(traccia), file_offset + lenI, risoluzione_TD)
 
       
 
    superior = Max(dur, superior)
 
     
 
  Next
 
 
      
 
      
  Return superior
 
 
 
 
  '''End'''
 
  '''End'''
 
 
'''Private''' Function legge_traccia(nmt As String, fine_traccia As Integer, rTD As Integer) As Float  <FONT Color=gray>' ''Legge una intera singola traccia Mtrk''</font>
 
 
    
 
    
  Dim tick, delta_ticks, lenI, totale_tick_traccia As Integer
+
  '''Private''' Function legge_var(mf As File) As Integer  <FONT Color=gray>' ''Legge un numero a lunghezza-variabile (Tempo Delta)''</font>
  Dim c, ultimo_cmd, cmd, tipo_cmd As Byte
 
  Dim f As Float
 
  Dim tempus, t1 As String
 
 
  <FONT Color=gray>' ''L'attuale posizione del puntatore nel file Midi è dopo i byte di identificazione e di lunghezza della traccia:''</font>
 
  While file_offset < fine_traccia
 
    delta_ticks = legge_var()
 
   
 
    If delta_ticks < 0 Then Break
 
   
 
    tick += delta_ticks
 
   
 
    Read #fl, c
 
    file_offset += 1
 
   
 
    If c < 0 Then Break
 
   
 
    If c And 128 Then
 
      cmd = c
 
      If cmd < 240 Then ultimo_cmd = cmd
 
 
    Else
 
<FONT Color=gray>' ''Status Running:''</font>
 
      Read #fl, c
 
      Dec file_offset
 
      cmd = ultimo_cmd
 
      If Not cmd Then Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
   
 
    Endif
 
 
    tipo_cmd = cmd \ CInt(2 ^ 4)
 
 
    Select Case tipo_cmd
 
      Case 8 To 11
 
        legge_byte()
 
        legge_byte()
 
      Case 14
 
        legge_byte()
 
        legge_byte()
 
      Case 12 To 13
 
        legge_byte()
 
      Case 15
 
        Select Case cmd
 
          Case 240, 247
 
            lenI = legge_var()
 
            If lenI < 0 Then Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
            If cmd = 240 Then
 
              Inc lenI
 
              c = 1
 
            Else
 
              c = 1
 
            Endif
 
              For c = 0 To lenI - 1
 
                legge_byte()
 
              Next
 
              Break
 
 
 
          Case 255          <FONT Color=gray>' ''Meta-evento''</font>
 
            c = legge_byte()
 
            lenI = legge_var()
 
            If lenI < 0 Then Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
            Select Case c
 
              Case 33
 
                If lenI < 1 Then Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
                legge_byte()
 
                salto(lenI - 1)
 
              Case 47                    <FONT Color=gray>' ''Fine traccia''</font>
 
                totale_tick_traccia = tick
 
                If nmt = "1" Then t1 = "  (del Tempo)"
 
                f = (((60000000 / Fix(60000000 / Val("&" & bpm$))) / rTD) * totale_tick_traccia) / 1000000
 
                If f > 0 Then tempus = Str(Date(0, 0, 0, 0, 0, 0, f * 1000))
 
                If IsNull(tempus) Then tempus = "00:00:00"
 
                Print "Traccia";; nmt; ": "; "  "; tempus; t1
 
                Print "------------------------------------"
 
                 
 
                Return f
 
 
 
              Case 81
 
                If lenI < 3 Then Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
                bpm$ = Hex(legge_byte(), 2)
 
                bpm$ &= Hex(legge_byte(), 2)
 
                bpm$ &= Hex(legge_byte(), 2)
 
                salto(lenI - 3)
 
              Case Else        ' Ignora gli altri Meta-eventi
 
                salto(lenI)
 
 
            End Select
 
          Case Else    ' Comando Fx non valido
 
            Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
        End Select
 
      Case Else
 
        Error.Raise("Dati Midi non validi (offset " & file_offset & ") !")
 
    End Select
 
   
 
  Wend
 
 
 
'''End'''
 
 
 
   
 
   
'''Private''' Function legge_var() As Integer  <FONT Color=gray>' ''Legge un numero a lunghezza-variabile (tempo Delta)''</font>
+
   Dim vl As Integer
 
 
   Dim valore As Integer
 
 
   Dim c As Byte
 
   Dim c As Byte
 
    
 
    
  Read #fl, c
+
  Repeat
  valore = c And 127
+
    Read #mf, c
  If c And 128 Then
+
    vl = Shl(vl, 7) Or (c And 127)
    Read #fl, c
+
  Until Not (c And 128)
    valore = (valore * CInt(2 ^ 7)) Or (c And 127)
 
    If c And 128 Then
 
      Read #fl, c
 
      valore = (valore * CInt(2 ^ 7)) Or (c And 127)
 
      If c And 128 Then
 
        Read #fl, c
 
        valore = (valore * CInt(2 ^ 7)) Or c
 
        If c And 128 Then Return -1
 
      Endif
 
    Endif
 
  Endif
 
 
 
  Return valore
 
 
 
'''End'''
 
 
 
'''Private''' Function legge_byte() As Byte
 
 
 
  Dim b As Byte
 
 
 
  Inc file_offset
 
 
    
 
    
  Read #fl, b
+
  Return vl
   
 
  Return b
 
 
    
 
    
 
  '''End'''
 
  '''End'''
 
 
'''Private''' Procedure salto(b As Byte)
 
 
    
 
    
  While b > 0
+
  '''Private''' Function DurataParziale(bpm As Integer, del As Short, par As Integer) As Float
    legge_byte()
 
    Dec b
 
  Wend
 
  file_offset += b
 
   
 
'''End'''
 
 
 
  '''Private''' Function legge_dal_file(by As Short) As Integer
 
 
    
 
    
  Dim valore As Integer
+
   Return CFloat((((60000000 / bpm) / del) * par) / 1000000)
  Dim b As Byte
 
    
 
  Do
 
    Read #fl, b
 
    If b = -1 Then Return -1
 
    valore = (valore * CInt(2 ^ 8)) Or b
 
    Dec by
 
  Loop Until by = 0
 
   
 
  Return valore
 
 
    
 
    
 
  '''End'''
 
  '''End'''

Versione attuale delle 17:27, 12 giu 2021

Il procedimento, seguito per ottenere la durata in secondi di un file Midi deve tenere in debita considerazione la circostanza che all'interno di un brano musicale possono insistere una o più variazioni del tempo metronomico. La durata del file Midi rappresenta così la somma delle singole durate determinate dagli eventuali cambi del tempo metronomico all'interno del file Midi.

Ciò richiede innanzitutto la conoscenza dei seguenti elementi:

  • tempo metronomico: movimenti (battute) per minuto (bpm), che si otterrà a sua volta dallo specifico Meta-evento FF 51;
  • tick reali dell'intera traccia Midi più grande, ossia la quantità di tick ottenuti dalle somme dei Tempi Delta (quest'ultimi convertiti ciascuno dal proprio formato a lunghezza variabile, nel quale sono espressi nel file Midi) fra ogni evento Midi e quello immediatamente successivo;
  • risoluzione del Tempo Delta (TΔ), espressa in ordine Big-Endian nel 13° e nel 14° byte del file Midi.

Pertanto, per ciascun "tratto" parziale di durata devono essere ottenuti il tempo metronomico (bpm), leggendolo dall'apposito Meta-evento FF 51, e i tick reali. Da tali elementi, considerando anche la risoluzione del Tempo Delta (TΔ), si otterrà per ogni "tratto" la durata in secondi, adottando la seguente formula:

((60 / bpm) / risoluzione_TΔ) * tick_reali = secondi

Successivamente bisogna ricavare anche il tempo metronomico e la quantità di tick reali maggiore fra le tracce (MTrk), e da questi due elementi, unitamente alla costante risoluzione del Tempo Delta, si otterrà la durata in secondi del "tratto finale" (per "tratto finale" qui intendiamo la quantità di Tempo Delta compresa fra l'ultimo Meta-evento FF 51 e il Meta-evento di chiusura FF 2F 00 della traccia avente la quantità maggiore di tick rispetto alle altre).

In ogni caso va ricordato che il valore predefinito del tempo metronomico è pari a 120 bpm.

Si potrà avere dunque, ad esempio, una situazione di questo genere:

0------FF51--------FF51----------FF51--------------FF2F00   (Traccia Midi di maggiore durata)
| 120        bmp1         bmp2   |        bmp3     |
|______|___________|_____________|_________________|
     tratto iniziale durata         tratto finale
|__________________________________________________|
           Durata totale del file Midi

In altri termini si procederà a:

1) estrarre il numero dei tick reali compresi fra l'inizio assoluto delle tracce Midi (punto TΔ = 0) e l'ulimo Meta-evento FF 51, ossia fino all'ultimo Tempo Delta precedente l'ultimo Meta-evento FF 51): "1° tratto" della durata del file Midi. Questo andrà ottenuto estraendo i tick reali per ogni tratto compreso tra i vari Meta-eventi FF 51 del "1° tratto".

2) estrarre il numero dei tick reali più grande fra le tracce esistenti del file Midi. Ciò significa che si dovrà ottenere il numero di tick reali della traccia che dura di più.

3) ottenere i tick reali del "tratto finale" più lungo fra le tracce esistenti, sottraendo i tick reali del "tratto iniziale" (punto 1) ai tick reali della traccia più duratura (punto 2).

4) convertire in secondi separatamente i tick reali di ciascun tratto costituente il "tratto iniziale".

5) convertire in secondi i tick reali del "tratto finale".

6) sommare i valori temporali, espressi in secondi, dei singoli tratti (punto 4) costituenti il "tratto iniziale" della durata del file Midi.


Esempio pratico:
a) 77959 tick reali della traccia più duratura;
b) 52992 tick reali del "tratto iniziale";
c) 77952 - 52992 = 24960 tick reali del "tratto finale" più lungo fra le tracce esistenti;
d) conversione in secondi di ciascun singolo tratto costituente il "tratto iniziale" della durata del file Midi;
e) secondi_tratto_iniziale + secondi_tratto_finale = durata effettiva del file Midi


Dunque, per conoscere la durata di un file Midi mediante le sole risorse di Gambas, è possibile utilizzare un codice come il seguente, nel quale si otterranno anche le durate delle singole tracce MTrk presenti nel file ed alcune generiche informazioni:

Public Sub Main()
 
 Dim fl As File
 Dim fileMidi, s As String
 Dim hbpm, tot, mx, tratto1 As Integer
 Dim td, bpm, c As Short
 Dim tr, b, n, av As Byte
 Dim cmd, tipocmd, ultimo As Byte
 Dim f, durata As Float
  
 fileMidi = "/percorso/del/file.mid"
 Print "File Midi:         "; fileMidi
 
 fl = Open fileMidi For Read
 If IsNull(fl) Then Error.Raise("Impossibile aprire il file !")
 
 Read #fl, s, 4
 If s <> "MThd" Then Error.Raise("Il file non è uno standard Midi !")
 Print "Dimensione:    "; Lof(fl); " byte"
 Seek #fl, 9
 Read #fl, c
 Print "Tipo file:         "; c
 Read #fl, tr
 Print "Numero tracce:   "; Format(tr, "###")
 Read #fl, td
 td = Rol(td, 8)
 Print "Risoluzione TΔ:  "; Format(td, "###")
 Avanza(fl, 8)
 
 bpm = 120
 
 Repeat
   tot = 0
   Do
     tot += legge_var(fl)
     Read #fl, b
     If b And 128 Then   ' Status running
       cmd = b
       If b < &F1 Then ultimo = cmd
       av = 2
     Else
       cmd = ultimo
       av = 1
     Endif
     tipocmd = Shr(cmd, 4)
     Select Case tipocmd
       Case 8 To 11
         Avanza(fl, av)
       Case 12 To 13 
         Avanza(fl, 1)
       Case 14
         Avanza(fl, av)
       Case 15
         If b = &F0 Then          ' Evento SysEx
           Repeat
             b = Read #fl As Byte
           Until b = &F7
         Else
           Read #fl, b
           Select Case b
             Case &51
               durata += DurataParziale(bpm, td, tot) 
               tratto1 += tot
               tot = 0
               Avanza(fl, 1)
               hbpm = 0
               For c = 2 To 0 Step -1
                 Read #fl, n
                 hbpm += Shl(CInt(n), 8 * c)
               Next
               bpm = 60000000 / hbpm
             Case &2F
               mx = Max(mx, tot)
               Exit
             Case Else
               Read #fl, b
               Avanza(fl, b)
           End Select
         Endif
     End Select
   Loop
   Dec tr
   If tr > 0 Then Avanza(fl, 9)
 Until tr = 0
 
 fl.Close
 
 f = DurataParziale(bpm, td, Max(mx, tratto1) - tratto1)
 
 Print "\nDURATA:       \e[31m\e[1m"; CStr(Time(0, 0, 0, (f + durata) * 1000)); "\e[0m"
 
End
 
 
Private Procedure Avanza(mf As File, av As Byte)
 
 Dim b, n As Byte
  
 For b = 1 To av
   Read #mf, n
 Next
   
End
 
Private Function legge_var(mf As File) As Integer   ' Legge un numero a lunghezza-variabile (Tempo Delta)

 Dim vl As Integer
 Dim c As Byte
 
 Repeat
   Read #mf, c
   vl = Shl(vl, 7) Or (c And 127)
 Until Not (c And 128)
 
 Return vl
 
End
 
Private Function DurataParziale(bpm As Integer, del As Short, par As Integer) As Float
 
  Return CFloat((((60000000 / bpm) / del) * par) / 1000000)
 
End