Ottenere un file di dati audio grezzi da un file .pat

Da Gambas-it.org - Wikipedia.

I file .pat, considerati in questa pagina, sono file, ideati da Gravis Ultrasound (GUS), contenenti campioni d'onda di strumenti musicali per dare il supporto sonoro al sistema Midi mediante appunto la sintesi wavetable.

La differenza fra tali patch di strumenti e il soundfont con estensione .sf2 sta nel fatto che, mentre quest'ultimi contengono le forme d'onda campionate di uno o di più strumenti musicali e la loro configurazione compatibile con lo standard GM, i file .pat contengono le forme d'onda campionate di un solo strumento musicale. La configurazione degli strumenti musicali, anche secondo lo standard GM, nel caso dei file .pat, è stabilita all'interno di un separato ed apposito file con estensione .cfg .

Ad ogni modo il formato .pat è considerato ormai vecchio. Si preferisce, oggi, invece utilizzare possibilmente i SoundFont .sf2. |1|


Struttura del file .pat

Il file .pat è sostanzialmente suddiviso in due blocchi.
Il primo blocco è formato da dati informativi per complessivi 335 byte, mentre il secondo blocco è formato dai dati audio grezzi.
Possiamo suddividere il primo blocco in due sotto-blocchi: i dati che formano il primo sotto-blocco (dal 1° byte al 238° byte) contengono le informazioni specifiche del file in quanto tale; i dati del secondo sotto-blocco (dal 239° byte al 335° byte) contengono informazioni specifiche del campione d'onda.

In dettaglio la struttura del file .pat è la seguente (tra parentesi il numero di byte di memoria occupati).

"GF1PATCH110 " oppure  "GF1PATCH100 " (12 byte - header del file):
"ID#000002 " (10 byte - l'ID Gravis Ultrasound)
eventuale descrizione (60 byte. I byte vuoti assumono il valore zero)
instruments (1 byte)
Voices (1 byte)
canali (1 byte)
waveforms (2 byte)
master volume (2 byte)
dimensione dati (4 byte)
byte riservati (36 byte)
instrument (1 byte)
nome dello strumento (16 byte)
instrument size (4 byte)
layers (1 byte)
byte riservati (40 byte)
layer duplicate (1 byte)
layer (1 byte)
dimensione layer (4 byte)
numero di campioni d'onda contenuti (1 byte)
byte riservati (40 byte)
nome del campione d'onda (7 byte)
fractions (1 byte)
dimensione del campione d'onda (4 byte)
inizio del loop (4 byte)
fine del loop (4 byte)
frequenza del campione d'onda (2 byte)
frequenza bassa del campione d'onda (4 byte)
Frequenza alta del campione d'onda (4 byte)
root frequency (4 byte)
intonazione (2 byte)
panning (1 byte)
envelope rate (1 byte)
envelope rate (1 byte)
envelope rate (1 byte)
envelope rate (1 byte)
envelope rate (1 byte)
envelope rate (1 byte)
envelope offset (1 byte)
envelope offset (1 byte)
envelope offset (1 byte)
envelope offset (1 byte)
envelope offset (1 byte)
envelope offset (1 byte)
tremolo sweep (1 byte)
tremolo rate (1 byte)
tremolo depth (1 byte)
vibrato sweep (1 byte)
vibrato rate (1 byte)
vibrato depth (1 byte)
modes (1 byte)
scale frequency (2 byte)
scale factor (2 byte)
byte riservati (36 byte)

Di seguito mostriamo un esempio pratico di un intero 1° blocco:

47 46 31 50 41 54 43 48 31 31 30 00 49 44 23 30 30
30 30 30 32 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0e 00
07 00 7F 00 00 D3 07 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 44 75 6C 63 69
6d 65 72 00 00 00 00 00 00 00 00 00 d6 07 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 92 D5 07 00 07 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 44 75 6C 63 69 6D 65 00 8E 43 01 00 AC 2F 01 00
8C 43 01 00 C4 79 DE 3F 00 00 04 AA 02 00 82 3D 02
00 01 00 07 3F 3F 3F 8B 3F 3F F6 F6 F6 00 00 00 00
D4 00 00 D4 00 65 40 00 00 04 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 (seguono i dati audio grezzi)


File .pat contenenti più forme d'onda

I file .pat possono contenere anche più campionamenti d'onda (multicampionamento), migliorando così la qualità sonora in riproduzione.

In questo caso la struttura del file diventa più complessa ovviamente; ed in particolare il file avrà l'intero previsto 1° blocco, quindi a seguire i dati audio del primo campionamento. Immediatamente dopo si avrà il sotto-blocco contenente le informazioni specifiche del secondo campionamento (a partire dai byte del relativo nome del campione d'onda), ed a seguire i suoi dati audio; e così via.


Ricavare i dati audio grezzi

Un codice per ricavare dal file .pat i dati audio grezzi di ciascun campionamento può essere ad esempio il seguente:

Public Sub Main()

 Dim fl, percorsoFilePAT As String
 Dim ff As New Byte[]
 Dim num_campioni, j As Byte
 Dim nomeFileBase, nome_onda, dim_onda$, frequenza$ As String
 Dim conta, k As Integer
 

   percorsoFilePAT = "percorso/del/file.pat"
   
   fl = File.Load(percorsoFilePAT)
   
   ff = ff.FromString(fl)
   
' Effettua le verifiche sul file:
   If Left(fl, 9) <> "GF1PATCH1" Then Error.Raise("Il file caricato non è un file .pat !")
   
   If ff[82] > 1 Then Error.Raise("Non è possibile gestire patch con strumenti superiori ad 1 !")
   
   If ff[151] > 1 Then Error.Raise("Non è possibile gestire strumenti con layer superiori ad 1 !")

' Ottiene il numero di campioni d'onda contenuti nel file:
   num_campioni = ff[198]    ' 198° byte del primo blocco
   
   Print "Il file presenta "; num_campioni; " campioni d'onda dello strumento.\n\n"
   
   For j = 131 To 147
     If IsLetter(Chr(ff[j])) Or (ff[j] = 32) Then nomeFileBase &= Chr(ff[j])
   Next

' Effettua le verifiche sui campioni d'onda contenuti nel file:
   conta = 238
   
   For j = 0 To num_campioni - 1
     
     Print "Descrizione del " & (j + 1) & "° campione d'onda:"
     
     For k = conta + 12 To conta + 9 Step -1
       dim_onda$ &= Hex(ff[k], 2)
     Next
     Print "Dimensione del campione onda: "; Val("&" & dim_onda$); " byte"

     For k = conta + 22 To conta + 21 Step -1
       frequenza$ &= Hex(ff[k])
     Next
     Print "Frequenza di campionamento: "; Val("&" & frequenza$) & " hrz"

     File.Save("/tmp" &/ nomeFileBase & CStr(j) & ".raw", Mid(fl, conta + 98, Val("&" & dim_onda$)))
     Print "Effettuata scrittura del file: /tmp" &/ nomeFileBase & CStr(j) & ".raw"
     
     conta += Val("&" & dim_onda$) + 96

     nome_onda = Null
     dim_onda$ = Null
     frequenza$ = Null
     
     Print "------------------------------------\n"

   Next

End


Note

[1] Si vedano al riguardo le seguenti pagine: