Autore Topic: Lettura waveform di un file audio  (Letto 1138 volte)

Offline esnho

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Lettura waveform di un file audio
« il: 22 Ottobre 2013, 17:13:03 CEST »
0
Ciao,
sto cercando di estrapolare dai file audio(più tipi di file ci sono e meglio è) i valori double o float della forma d'onda, non so se mi spiego, in pratica mi servierebbero i dati grezzi estratti dai byte del file audio. Questi dati mi servono per visualizzare la forma d'onda dei file caricati.
Ho trovato una libreria sviluppata da Google comoda ma, mi estrae dei valori assoluti. Quindi la visualizzazione che riesco ad ottenere è una visualizzazione "con il trucco" nel senso che posso mostrare solo una forma specchiata del'ampiezza assoluta dei frames.

Non so se mi avete capito, in pratica invece di avere i valori da -1 a 1 dell'onda sonora ho solo i valori assoluti dell'ampiezza dei campioni.


questa è l'onda(non zoomata) che ottengo ora, come si nota l'onda è simmetrica, quindi non reale...
[img src="https://dl.dropboxusercontent.com/u/18517799/Screenshot_2013-10-22-17-04-48.png"][/img]
« Ultima modifica: 22 Ottobre 2013, 17:16:05 CEST da esnho »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Lettura waveform di un file audio
« Risposta #1 il: 22 Ottobre 2013, 18:19:05 CEST »
0
Il fatto che l'audio sia codificato in questo modo è un dato fisico, perchè essendo il suono una successione di compressioni e rarefazioni dell'aria rispetto ad un valore di riposo, è abbastanza normale che appaia specchiato.

Per capirssi: un singolo campione della forma d'onda non ha nessun significato perchè a generare il suono è la sequenza di campioni. Per esempio se i campioni tracciano una sinusoide (positiva e negativa), quello che sentirai è un tono puro a alla frequenza della sinusoide.

Se vuoi estrarre informazioni sulle frequenze di un forma d'onda audio, ne farai probabilmente una FFT; per il volume probabilmente ci si rifa alle ampiezze massime o ai valori efficaci. Ma sulle elaborazioni tipiche dei file audio so poco più che la teoria di base, dipende da cosa devi fare.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Lettura waveform di un file audio
« Risposta #2 il: 22 Ottobre 2013, 18:57:29 CEST »
0
questa è l'onda(non zoomata) che ottengo ora, come si nota l'onda è simmetrica, quindi non reale...
Non capisco perchè quello che hai postato non dovrebbe essere reale. E' una visualizzazione piuttosto comune di una forma d'onda e la trovi anche in programmi di editing audio su personal computer.

Quello che dice bradipao è corretto.

Diciamo che ci sono 3 livelli differenti.
Il primo livello è quello "naturale" cioè la parte interna del tuo orecchio risponde alle sollecitazioni delle onde sonore e ti permette di percepire il suono.
Il secondo livello è la generazione del suono da un dispositivo che per forza di cose non può essere continua ma procede a "samples" cioè divide un secondo in una serie di istanti.
Il terzo livello è il modo in cui tu salvi l'informazione cioè il file audio. Può essere non compresso o compresso (tipo mp3).

Quello che a te interessa è il secondo livello, cioè il file già decompresso dalla libreria pronto per essere suonato/analizzato.

Tu hai una serie di parametri che definiscono il suono:

bit (8-16-24)
numero di canali (mono-stereo)
frequenza di sampling (8192 a 48000 sample al secondo)

Un cd è 16 bit stereo 44100 samples al secondo.
Un codec per una telefonata è probabilmente 8 bit 8khz mono.

I tuoi valori tra -1 e 1 li determini conoscendo i bit. In teoria la soluzione sarebbe semplice se non fosse che i numeri rappresentabili sono dispari, cioè sono pari se includi lo zero.

Se il sample è a 16-bit puoi rappresentare numeri compresi tra 0 e 65535. In pratica l'audio è sempre codificato con numeri complemento a 2 cioè tra -32768 e 32767. A 8 bit il discorso non cambia, si usano valori tra -128 e 127.

Essendo "dispari" non puoi fare semplicemente una divisione ma ci sono varie strategie.
Lo 0 è sempre zero quindi non ti interessa per cosa lo vai a dividere.
Il numero più piccolo è quello positivo, quindi se dividi 127 per 127 ti viene uno.
Il numero negativo è più grande quindi se dividi per 127 ti viene -1,qualcosa.
Se ti sta bene introdurre un piccolo errore fai così:

Codice (Java): [Seleziona]
float valoresample = ((float)valoreoriginale)/127.0f; // 32767.0f se 16-bit
if( valoresample < -1.0f )
 valoresample = -1.0f;

Poi se ti vuoi divertire a fare conversioni esoteriche trovi svariata letteratura in proposito.

 :D

Offline esnho

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Lettura waveform di un file audio
« Risposta #3 il: 23 Ottobre 2013, 02:36:57 CEST »
0
Bene,
conosco anch'io un po' di teoria del suono e vi assicuro che non è simmetrico, proprio perché si parla di suoni complessi. Inoltre dato che un suono può essere generato esso può anche avere dei frammenti che non scendono mai sotto lo 0 (usando la convenzione -1 1) o viceversa. Sono campioni "rari", molto probabilmente glitch.

Quello che interessa a me si interpone tra il secondo e il terzo livello di undead. Ovvero, vorrei capire (anche implementando piccoli errori) come estrapolare i valori dei singoli samples per poter costruire una visualizzazione che, se zoomata, mostri l'onda (ovviamente interpolata) di file audio di diversi formati. Speravo di non  dover lavorare con i byte e la decodifica e quindi mi chiedevo se ci fossero librerie, o codici open source, o riferimenti da poter utilizzare.

Al momento sono perso nel tentativo di avere dei dati solidi da cui partire.

Quell'onda che ho postato è "finta", nel senso che utilizzando la libreria che ho linkato ottengo solo i valori positivi e, per creare l'illusione di onda ristampo a schermo gli stessi valori specchiati. Questo perché l'ampiezza(facilmente ottenibile con quella libreria) è un valore assoluto, mentre l'onda sonora, per convenzione, è rappresentata da una sequenza di valori sia positivi che negativi. Ho provato a comprendere il codice di quella libreria ma speravo che ne esistesse un'altra che non mi costringa a riscrivere la decodifica dei file secondo un criterio più scientifico e capace di essere rappresentato in maniera grafica più corretta.

Spero di essere stato un po' più chiaro. :-)

P. S. : non mi interessa l'analisi di frequenza (in questo caso) ma la waveform "grezza"

P. P. S. : per fare capire, una visualizzazione tipo questa, ma di file audio di diversi formati Visualizing Sound From The Microphone - Android Development | Dream.In.Code
« Ultima modifica: 23 Ottobre 2013, 02:42:50 CEST da esnho »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Lettura waveform di un file audio
« Risposta #4 il: 23 Ottobre 2013, 08:11:18 CEST »
0
Spero di essere stato un po' più chiaro. :-)

Sinceramente adesso mi rendo conto di aver capito meno di prima.  :-(
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline esnho

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Lettura waveform di un file audio
« Risposta #5 il: 23 Ottobre 2013, 13:04:35 CEST »
0
Il fatto è questo, voglio estrarre i dati grezzi dell'audio, l'onda pura. Punto.
Questi dati poi li utilizzerò per creare una visualizzazione d'onda ma non è questo il problema.

Edit:
intendo proprio l'estrapolazione di quello che undead chiama valoreoriginale
« Ultima modifica: 23 Ottobre 2013, 13:28:10 CEST da esnho »

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Lettura waveform di un file audio
« Risposta #6 il: 23 Ottobre 2013, 14:32:37 CEST »
0
Non ho mai usato quella libreria ma l'onda secondo me non è simmetrica se tu fai uno zoom secondo me ti viene una forma d'onda con positivi e negativi. Puoi provare a fare uno zoom della visualizzazione da quella libreria rappresentare cioè mezzo secondo o 1 decimo di secondo per volta invece di tot secondi?

Offline esnho

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Lettura waveform di un file audio
« Risposta #7 il: 23 Ottobre 2013, 16:59:53 CEST »
0
guarda, la visualizzazione grafica l'ho scritta io, quindi sono sicuro che è simmetrica, per quel che riguarda i dati grezzi, io credo che siano solo valori assoluti riguardanti l'ampiezza del campione senza tenere conto della descrizione scientifica del suono, quindi in realtà dovrebbe essere simmetrica.

il codice che legge i frame è questo e fa un'operazione di confronto di valore assoluto, non mi intendo di codifica audio, quindi non capisco se il loro è un'approccio approssimativo o se, con poche modifiche si ottiene ciò che cerco, sono certo che salvando nell'array i valori non assoluti, continuo ad ottenere valori solo assoluti... non capisco.

Ora vedo di capire che cos'è l'array mFrameOffsets, effettivamente ci faccio caso solo ora.

Codice (Java): [Seleziona]
                while (i < chunkLen) {
                    int oneFrameBytes = mFrameBytes;
                    if (i + oneFrameBytes > chunkLen) {
                        i = chunkLen - oneFrameBytes;
                    }

                    stream.read(oneFrame, 0, oneFrameBytes);
                    int maxGain = 0;
                    for (int j = 1; j < oneFrameBytes; j += 4 * mChannels) {
                        int val = java.lang.Math.abs(oneFrame[j]);
                        if (val > maxGain) {
                            maxGain = val;
                        }
                    }

                    mFrameOffsets[frameIndex] = mOffset;
                    mFrameLens[frameIndex] = oneFrameBytes;
                    mFrameGains[frameIndex] = maxGain;

                    frameIndex++;
                    mOffset += oneFrameBytes;
                    i += oneFrameBytes;
                }

Post unito: 23 Ottobre 2013, 17:10:03 CEST
Ecco un'estratto dello stamp dell'array di offset e del valore dei gain a confronto, sinceramente, non capisco che sia offset.


10-23 17:06:59.934: V/Offset/value(8101): 44 / 1
10-23 17:06:59.934: V/Offset/value(8101): 3572 / 2
10-23 17:06:59.934: V/Offset/value(8101): 7100 / 4
10-23 17:06:59.934: V/Offset/value(8101): 10628 / 5
10-23 17:06:59.934: V/Offset/value(8101): 14156 / 17
10-23 17:06:59.934: V/Offset/value(8101): 17684 / 24
10-23 17:06:59.934: V/Offset/value(8101): 21212 / 31
10-23 17:06:59.934: V/Offset/value(8101): 24740 / 31
10-23 17:06:59.934: V/Offset/value(8101): 28268 / 28
10-23 17:06:59.934: V/Offset/value(8101): 31796 / 23
10-23 17:06:59.934: V/Offset/value(8101): 35324 / 35
10-23 17:06:59.934: V/Offset/value(8101): 38852 / 35
10-23 17:06:59.934: V/Offset/value(8101): 42380 / 35
10-23 17:06:59.934: V/Offset/value(8101): 45908 / 34
10-23 17:06:59.934: V/Offset/value(8101): 49436 / 35
10-23 17:06:59.934: V/Offset/value(8101): 52964 / 35
10-23 17:06:59.934: V/Offset/value(8101): 56492 / 33
10-23 17:06:59.934: V/Offset/value(8101): 60020 / 41
10-23 17:06:59.934: V/Offset/value(8101): 63548 / 42
10-23 17:06:59.934: V/Offset/value(8101): 67076 / 34
10-23 17:06:59.934: V/Offset/value(8101): 70604 / 33
10-23 17:06:59.934: V/Offset/value(8101): 74132 / 38
10-23 17:06:59.934: V/Offset/value(8101): 77660 / 39
10-23 17:06:59.934: V/Offset/value(8101): 81188 / 36
10-23 17:06:59.934: V/Offset/value(8101): 84716 / 31
10-23 17:06:59.934: V/Offset/value(8101): 88244 / 42
10-23 17:06:59.934: V/Offset/value(8101): 91772 / 52
10-23 17:06:59.934: V/Offset/value(8101): 95300 / 44
10-23 17:06:59.934: V/Offset/value(8101): 98828 / 39
10-23 17:06:59.934: V/Offset/value(8101): 102356 / 44
10-23 17:06:59.934: V/Offset/value(8101): 105884 / 41
10-23 17:06:59.934: V/Offset/value(8101): 109412 / 40
10-23 17:06:59.934: V/Offset/value(8101): 112940 / 41
10-23 17:06:59.934: V/Offset/value(8101): 116468 / 41
10-23 17:06:59.934: V/Offset/value(8101): 119996 / 35
10-23 17:06:59.934: V/Offset/value(8101): 123524 / 34
10-23 17:06:59.934: V/Offset/value(8101): 127052 / 42
10-23 17:06:59.934: V/Offset/value(8101): 130580 / 37
10-23 17:06:59.934: V/Offset/value(8101): 134108 / 36
10-23 17:06:59.934: V/Offset/value(8101): 137636 / 33
10-23 17:06:59.934: V/Offset/value(8101): 141164 / 35
10-23 17:06:59.934: V/Offset/value(8101): 144692 / 27
10-23 17:06:59.934: V/Offset/value(8101): 148220 / 30
10-23 17:06:59.934: V/Offset/value(8101): 151748 / 31
10-23 17:06:59.934: V/Offset/value(8101): 155276 / 35
10-23 17:06:59.934: V/Offset/value(8101): 158804 / 24
10-23 17:06:59.934: V/Offset/value(8101): 162332 / 28
10-23 17:06:59.934: V/Offset/value(8101): 165860 / 30
10-23 17:06:59.934: V/Offset/value(8101): 169388 / 30
10-23 17:06:59.934: V/Offset/value(8101): 172916 / 25
10-23 17:06:59.934: V/Offset/value(8101): 176444 / 22
10-23 17:06:59.934: V/Offset/value(8101): 179972 / 30
10-23 17:06:59.934: V/Offset/value(8101): 183500 / 30
10-23 17:06:59.934: V/Offset/value(8101): 187028 / 29
10-23 17:06:59.934: V/Offset/value(8101): 190556 / 22
10-23 17:06:59.934: V/Offset/value(8101): 194084 / 25
10-23 17:06:59.934: V/Offset/value(8101): 197612 / 26
10-23 17:06:59.944: V/Offset/value(8101): 201140 / 22
10-23 17:06:59.944: V/Offset/value(8101): 204668 / 21
10-23 17:06:59.944: V/Offset/value(8101): 208196 / 21
10-23 17:06:59.944: V/Offset/value(8101): 211724 / 23
10-23 17:06:59.944: V/Offset/value(8101): 215252 / 20
10-23 17:06:59.944: V/Offset/value(8101): 218780 / 19
10-23 17:06:59.944: V/Offset/value(8101): 222308 / 17
10-23 17:06:59.944: V/Offset/value(8101): 225836 / 19
10-23 17:06:59.944: V/Offset/value(8101): 229364 / 22
10-23 17:06:59.944: V/Offset/value(8101): 232892 / 19
10-23 17:06:59.944: V/Offset/value(8101): 236420 / 19
10-23 17:06:59.944: V/Offset/value(8101): 239948 / 18
10-23 17:06:59.944: V/Offset/value(8101): 243476 / 19
10-23 17:06:59.944: V/Offset/value(8101): 247004 / 16
10-23 17:06:59.944: V/Offset/value(8101): 250532 / 18
10-23 17:06:59.944: V/Offset/value(8101): 254060 / 17
10-23 17:06:59.944: V/Offset/value(8101): 257588 / 16
10-23 17:06:59.944: V/Offset/value(8101): 261116 / 15
10-23 17:06:59.944: V/Offset/value(8101): 264644 / 15
10-23 17:06:59.944: V/Offset/value(8101): 268172 / 13
10-23 17:06:59.944: V/Offset/value(8101): 271700 / 14
10-23 17:06:59.944: V/Offset/value(8101): 275228 / 14
10-23 17:06:59.944: V/Offset/value(8101): 278756 / 12
10-23 17:06:59.944: V/Offset/value(8101): 282284 / 16
10-23 17:06:59.944: V/Offset/value(8101): 285812 / 14
10-23 17:06:59.944: V/Offset/value(8101): 289340 / 13
10-23 17:06:59.944: V/Offset/value(8101): 292868 / 9
10-23 17:06:59.944: V/Offset/value(8101): 296396 / 12
10-23 17:06:59.944: V/Offset/value(8101): 299924 / 14
10-23 17:06:59.944: V/Offset/value(8101): 303452 / 13
10-23 17:06:59.944: V/Offset/value(8101): 306980 / 11
10-23 17:06:59.944: V/Offset/value(8101): 310508 / 13
10-23 17:06:59.944: V/Offset/value(8101): 314036 / 15
10-23 17:06:59.944: V/Offset/value(8101): 317564 / 11
10-23 17:06:59.944: V/Offset/value(8101): 321092 / 12
10-23 17:06:59.944: V/Offset/value(8101): 324620 / 14
10-23 17:06:59.944: V/Offset/value(8101): 328148 / 13
10-23 17:06:59.944: V/Offset/value(8101): 331676 / 12
10-23 17:06:59.944: V/Offset/value(8101): 335204 / 10
10-23 17:06:59.944: V/Offset/value(8101): 338732 / 13

« Ultima modifica: 23 Ottobre 2013, 17:10:03 CEST da esnho, Reason: Merged DoublePost »

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Lettura waveform di un file audio
« Risposta #8 il: 23 Ottobre 2013, 17:26:36 CEST »
0
A me sembra, ma potrei sbagliarmi, che questi facciao una cosa decisamente "grezza".

In pratica prendono un gruppo di byte della forma d'onda e calcolano il massimo.
Se vuoi faccio due calcoli per vedere quale è il tempo.

3528 bytes per chunk a 16 bit a due canali sono 882 samples per chunk. Se il file ha un sample rate di 22khz (cioè 22500 samples al secondo) e lo divid per 882 ti viene 25, se invece è a 44khz viene 50.

Quindi se il file è a qualità CD 1 secondo (1000 milllisecondi) diviso 50 = 20 millisecondi.

Per quanto mi è dato di vedere calcolano il valore assoluto del sample più grande in gruppi da 20 millisecondi (o 40 se sono 22khz) e poi semplicemente lo disegnano.

Una approssimazione, MOLTO APPROSSIMATA, della forma d'onda.

Se ho ragione i valori che ti servono sono semplicemente dentro oneFrame.

 ;-)




Post unito: 23 Ottobre 2013, 17:42:49 CEST
Ho letto che hai problemi a leggere i dati da oneFrame, mi era sfuggito

Quello che non mi piace è questo pezzo qua nel for:

4 * mChannels

In pratica salta 4 byte (cioè un int) per ogni canale (quindi analizza solo il primo canale) ma quando legge lo stream lo butta direttamente lì.
Lo stream legge byte per byte quindi immagino che oneFrame sia un byte[].

Ma se i dati sono a 16-bit il valore di oneFrame credo perda di significato... infatti partono da 1 e non da zero, come se saltassero il byte più significativo...
« Ultima modifica: 23 Ottobre 2013, 17:42:49 CEST da undead, Reason: Merged DoublePost »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Lettura waveform di un file audio
« Risposta #9 il: 23 Ottobre 2013, 18:34:01 CEST »
0
A occhio mFrameOffsets contiene l'array degli scostamenti (offset) ai quali iniziano i vari frame. Un riferimento all'indice dell'array a cui inizia il frame, niente di che. In numeri estratti da questo codice sono più che altro legati al volume del suono, che alla sua forma d'onda (che pare essere dentro oneFrame, visto che fa il valore assoluto : int val = java.lang.Math.abs(oneFrame[j]) ).
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline esnho

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Lettura waveform di un file audio
« Risposta #10 il: 29 Novembre 2013, 11:49:53 CET »
0
non ho risolto completamente la questione, intanto mi sto appoggiando ad una libreria per aprire i file wav,  è la musicg, questo è l'indirizzo

 musicg -
 
 
 Lightweight Java API for audio analysing, Android compatible - Google Project Hosting