Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    [Java] Catturare audio da microfono per ottenere dati float

    Salve a tutti,
    come da titolo, il mio intento sarebbe quello di catture audio da microfono per ottenere dati float, campionando a 8 KHz e quantizzando a 16 bit.
    Riesco ad ottenere un file .wav adoperando la classe TargetDataLine ma una successiva lettura mediante audioInputStream.read mi permette di ricavare solo array di tipo byte[].

    Quello che vorrei ottenere è sostanzialmente quanto segue : una unica sequenza di dati float su cui successivamente poter applicare tecniche di DSP.
    I computer sono incredibilmente veloci,
    accurati e stupidi. Gli uomini sono
    incredibilmente lenti, inaccurati e
    intelligenti. Insieme sono una potenza
    che supera l'immaginazione.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [Java] Catturare audio da microfono per ottenere dati float

    Originariamente inviato da Dedalo_shares
    ma una successiva lettura mediante audioInputStream.read mi permette di ricavare solo array di tipo byte[].

    Quello che vorrei ottenere è sostanzialmente quanto segue : una unica sequenza di dati float su cui successivamente poter applicare tecniche di DSP.
    Pur non essendo praticissimo della Sound API, credo al 99% che devi leggere tu i byte e conoscendo il formato (da un AudioFormat) cioè bits/sample, signed/unsigned, num.canali, ecc... componi tu un valore (intero o floating point) di ogni campione da uno o più byte.

    Insomma, è compito tuo.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Infatti in questo momento, considerando 2 byte per frame e detto bytes l'array di tipo byte[] che leggo dal .wav, stavo provando in questo modo..

    codice:
     float[] floats = new float[bytes.length >> 1];                        
     for (int i = 0, n = floats.length; i < n; i++)       
    {           
    floats[i] = (bytes[i * 2 + 0] << 8) + (bytes[i * 2 + 1] << 0);       }
    I computer sono incredibilmente veloci,
    accurati e stupidi. Gli uomini sono
    incredibilmente lenti, inaccurati e
    intelligenti. Insieme sono una potenza
    che supera l'immaginazione.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Dedalo_shares
    Infatti in questo momento, considerando 2 byte per frame e detto bytes l'array di tipo byte[] che leggo dal .wav, stavo provando in questo modo..

    codice:
     float[] floats = new float[bytes.length >> 1];                        
     for (int i = 0, n = floats.length; i < n; i++)       
    {           
    floats[i] = (bytes[i * 2 + 0] << 8) + (bytes[i * 2 + 1] << 0);       }
    No. A parte che bisogna vedere quanto leggi, come buffer, in byte (per evitare grattacapi dovrebbe essere un multiplo della lunghezza di 1 sample). Ma a parte questo non hai considerato che l'operatore << applica la numeric promotion al primo operando, quindi da byte a int e viene "esteso" il segno. Quindi se un byte è 0xA0, ti viene fuori un int 0xFFFFFFA0, il che sballa tutto.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Dal momento che credo di aver risolto, posto qui la soluzione :

    La conversione dipende dai dati estratti dall'AudioFormat.

    Considerando le seguenti caratteristiche:
    - Sample size : 2 bytes
    - Ordine dei byte : little endian
    - Encoding: PCM_SIGNED
    E' possibile scrivere quanto segue...

    codice:
       public static void decode(byte[] input, double[] output) 
    {  
          assert input.length == 2*output.length;  
          for(int i=0; i < output.length; i++) {  
               output[i] = (short)(((0xFF & input[2*i+1]) << 8) | (0xFF & input[2*i]))  
               output[i] = output[i] / Short.MAX_VALUE; // solo se si vuole normalizzare a [-1,1]  
           }  
        }
    I computer sono incredibilmente veloci,
    accurati e stupidi. Gli uomini sono
    incredibilmente lenti, inaccurati e
    intelligenti. Insieme sono una potenza
    che supera l'immaginazione.

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Dedalo_shares
    codice:
       public static void decode(byte[] input, double[] output) 
    {  
          assert input.length == 2*output.length;  
          for(int i=0; i < output.length; i++) {  
               output[i] = (short)(((0xFF & input[2*i+1]) << 8) | (0xFF & input[2*i]))  
               output[i] = output[i] / Short.MAX_VALUE; // solo se si vuole normalizzare a [-1,1]  
           }  
        }
    Confermo che tecnicamente mi pare corretto. Mi riferisco alla "composizione" del valore dai due byte low/high.
    Per quanto riguarda la "normalizzazione" c'è solo un piccolissimo dettaglio: uno short ha range -32768...+32767. Quindi -32768/32767 dà più (di pochissimo) di -1. È solo una finezza ma meglio tenerne conto.


    P.S. Le "asserzioni" servono per verificare che il proprio codice non abbia "bachi" .... NON che qualcuno lo usa "male" (ad esempio passando l'array 'input' di lunghezza incongruente con l'array 'output').
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Originariamente inviato da andbin
    Confermo che tecnicamente mi pare corretto. Mi riferisco alla "composizione" del valore dai due byte low/high.
    Per quanto riguarda la "normalizzazione" c'è solo un piccolissimo dettaglio: uno short ha range -32768...+32767. Quindi -32768/32767 dà più (di pochissimo) di -1. È solo una finezza ma meglio tenerne conto.


    P.S. Le "asserzioni" servono per verificare che il proprio codice non abbia "bachi" .... NON che qualcuno lo usa "male" (ad esempio passando l'array 'input' di lunghezza incongruente con l'array 'output').
    In effetti l'asserzione l'ho messa più a commento che per altro... nel mio codice uso solo quel formato (e in particolare quel numero di byte per sample) ergo è inutile.
    Ti ringrazio per la precisazione circa la normalizzazione (anche se fortunatamente devo utilizzare dati non normalizzati), quindi anche quella riga era solo un'aggiunta.

    P.s. Chiedo venia per i *piccoli* errori... ma programmo in Java da neanche una settimana.
    I computer sono incredibilmente veloci,
    accurati e stupidi. Gli uomini sono
    incredibilmente lenti, inaccurati e
    intelligenti. Insieme sono una potenza
    che supera l'immaginazione.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.