2016-01-19 6 views
8

Sto utilizzando AudioTrack per riprodurre una sequenza di onde sinusoidali, ma quando lo eseguo sul mio HTC M9, suona solo una parte dei campioni e la durata della riproduzione è casuale. e. g. Ho 20 toni da suonare, ma suona solo da 2 a 17,5 toni di loro. E sì, si fermerà anche a metà di un tono.Android AudioTrack non riproduce tutti i campioni

Ecco il mio codice, da un'altra risposta:

ArrayList<double[]> samples = new ArrayList<>(); 
    int numSamples = 0; 
    for (final ToneSegment seg : sequence) { 
     int num = seg.getDuration() * sampleRate/1000; 
     double[] sample = new double[num]; 
     for (int i = 0; i < num; ++i) { 
      sample[i] = Math.sin(2 * Math.PI * i * seg.getPitch()/sampleRate); 
     } 
     samples.add(sample); 
     numSamples += num; 
    } 

    byte generatedSnd[] = new byte[2 * numSamples]; 
    int idx = 0; 
    for (double[] sample : samples) { 
     for (final double dVal : sample) { 
      final short val = (short) ((dVal * 32767)); 
      generatedSnd[idx++] = (byte) (val & 0x00ff); 
      generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8); 
     } 
    } 

    audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
      sampleRate, AudioFormat.CHANNEL_OUT_MONO, 
      AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, 
      AudioTrack.MODE_STATIC); 
    audioTrack.write(generatedSnd, 0, generatedSnd.length); 
    audioTrack.play(); 

Qualcuno ha qualche idea? Grazie!

risposta

0

È probabile che la raccolta dei dati inutili causi questo problema. Stavo scrivendo questo codice in un metodo che ritorna immediatamente, poiché l'oggetto audioTrack perderà il riferimento ad esso. Se la raccolta dei dati inutili avviene durante la riproduzione, audioTrack verrà finalizzato e interromperà la riproduzione dei toni. Pertanto questo problema si verifica occasionalmente, a seconda di quanto è attivo il GC durante la riproduzione dei toni.

Quindi ho bisogno di mantenere il riferimento dell'oggetto AudioTrack fino al termine della riproduzione. Penso che ci sono molti modi per farlo, ma alla fine io uso il modo più semplice:

class Player { 
    private static AudioTrack sAudioTrack; 
} 

MediaPlayer ha anche questa trappola, ed è come ho trovato il problema dal momento che scriverà di log che sia finalizzato prima del rilascio.

2

Si sta utilizzando AudioTrack.MODE_STATIC pensato per brevi suoni e requisiti di bassa latenza, mentre è necessario utilizzare AudioTrack.MODE_STREAM. AudioTrack.MODE_STREAM è pensato per flussi più lunghi, ma non so quanto siano lunghi i tuoi campioni. Così si può cercare di cambiare AudioTrack:

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
     sampleRate, AudioFormat.CHANNEL_OUT_MONO, 
     AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, 
     AudioTrack.MODE_STREAM); 

Anche L'AudioTrack richiede la dimensione del buffer in byte, a breve ha bisogno di essere moltiplicati per due per calcolare la corretta quantità di byte necessari. Potresti modificarlo in questo modo:

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
     sampleRate, AudioFormat.CHANNEL_OUT_MONO, 
     AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length*2, 
     AudioTrack.MODE_STREAM); 
+0

Ho provato MODE_STREAM, ma è lo stesso. I miei campioni funzionano solo da 3 a 7 secondi. –

+0

Giocano per una durata casuale? Hai provato più brevi o altri campioni audio? E hai moltiplicato anche la quantità di byte? – jobbert

+0

Sì, ho provato altri campioni. Non sono durata casuale. Cosa significa moltiplicare la quantità di byte? –