2016-01-19 10 views
8

Ich benutze AudioTrack, um eine Sequenz von Sinuswellen zu spielen, aber wenn ich es auf meinem HTC M9 laufen lasse, spielt es nur einen Teil der Samples, und wie lange es gespielt wird, ist zufällig. e. G. Ich habe 20 Töne zu spielen, aber es spielt nur 2 bis 17.5 Töne von ihnen. Und ja, es wird sogar mitten in einem Ton stehen bleiben.Android AudioTrack spielt nicht alle Samples

Hier ist mein Code aus einer anderen Antwort:

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(); 

Hat eine Idee jemand? Vielen Dank!

Antwort

0

Es ist wahrscheinlich, die Garbage Collection dieses Problem verursacht. Ich habe diesen Code in einer Methode geschrieben, die sofort zurückkehrt, da das Objekt audioTrack den Verweis darauf verliert. Wenn während der Wiedergabe eine Speicherbereinigung stattfindet, wird audioTrack finalisiert und hört auf, Töne wiederzugeben. Daher tritt dieses Problem gelegentlich auf, je nachdem, wie aktiv der GC beim Abspielen von Tönen ist.

Also muss ich die AudioTrack Objektreferenz beibehalten, bis die Wiedergabe endet. Ich denke, es gibt viele Möglichkeiten, dies zu tun, aber schließlich verwende ich die einfachste Art und Weise:

class Player { 
    private static AudioTrack sAudioTrack; 
} 

MediaPlayer auch diese Falle hat und wie ich das Problem gefunden, da es log schreibt, dass es, bevor sie freigegeben finalisiert ist.

2

Sie verwenden AudioTrack.MODE_STATIC, das für kurze Sounds und niedrige Latenzanforderungen gedacht ist, während Sie AudioTrack.MODE_STREAM verwenden sollten. AudioTrack.MODE_STREAM ist für längere Streams gedacht, aber ich weiß nicht, wie lange Ihre Samples sind. So können Sie versuchen, und Audiotrack ändern:

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

Auch der Audiotrack erfordert die Puffergröße in Byte, ein kurzes Bedürfnisse mit zwei multipliziert werden, um die richtigen Menge des benötigten Bytes zu berechnen. Man könnte es hacken in wie folgt aus:

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

Ich habe MODE_STREAM ausprobiert, aber es ist dasselbe. Meine Samples spielen nur für 3 bis 7 Sekunden. –

+0

Sie spielen für eine zufällige Dauer? Haben Sie kürzere oder andere Audio-Samples ausprobiert? Und haben Sie die Anzahl der Bytes auch multipliziert? – jobbert

+0

Ja, ich habe andere Proben ausprobiert. Sie sind keine zufällige Dauer. Was ist die Anzahl der Bytes zu multiplizieren? –

Verwandte Themen