2010-12-13 5 views
8

두 개의 AudioTrack 인스턴스를 동시에 실행해야합니다. 그들은 다양한 샘플 속도로 연주하기 때문에 별도로 실행해야합니다. 나는 그들이 같은 스레드에서 그들을 실행하면, 그들은 "회전"을 발견했다. 나는 그들 자신의 스레드에서 각각을 실행하고 있지만 오디오가 끊기고 있습니다.Android : 여러 AudioTrack 인스턴스를 혼합하고 있습니까?

두 개의 인스턴스를 멋지게 만드려는 아이디어가 있습니까? 그렇지 않은 경우 두 개의 짧은 버퍼를 하나의 버퍼로 믹싱하는 데 대한 팁이 있습니다. 다른 샘플 속도로 재생하려고하는 경우에도 마찬가지입니다.

답변

11

나는 4 개의 audioTracks를 한꺼번에 연주하며 잘 연주하는 것 같습니다. HTC Desire 1.1ghz OC에 대한 테스트. 가끔씩 스레딩 문제가 발생합니다. 때로는 4 명이 모두 게임을하는 경우 스레드에 참여하려고 할 때 멈추지 않습니다. 더 많은 테스트를해야합니다. 는 여기에 주어진 경로

package com.ron.audio.functions; 

import java.io.BufferedInputStream; 
import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStream; 

import android.media.AudioFormat; 
import android.media.AudioManager; 
import android.media.AudioTrack; 

public class AudioPlayManager implements Runnable { 

private File fileName; 
private volatile boolean playing; 

public AudioPlayManager() { 
    super(); 
    setPlaying(false); 
} 

public void run(){ 
     // Get the length of the audio stored in the file (16 bit so 2 bytes per short) 
     // and create a short array to store the recorded audio. 
     int musicLength = (int)(fileName.length()/2); 
     short[] music = new short[musicLength]; 

     try { 
     // Create a DataInputStream to read the audio data back from the saved file. 
     InputStream is = new FileInputStream(fileName); 
     BufferedInputStream bis = new BufferedInputStream(is); 
     DataInputStream dis = new DataInputStream(bis); 

     // Read the file into the music array. 
     int i = 0; 
     while (dis.available() > 0) { 
      music[i] = dis.readShort(); 
      i++; 
     } 

     // Close the input streams. 
     dis.close();  

     // Create a new AudioTrack object using the same parameters as the AudioRecord 
     // object used to create the file. 
     AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 
               11025, 
               AudioFormat.CHANNEL_CONFIGURATION_MONO, 
               AudioFormat.ENCODING_PCM_16BIT, 
               musicLength, 
               AudioTrack.MODE_STREAM); 
     // Start playback 
     audioTrack.play(); 

     // Write the music buffer to the AudioTrack object 
     while(playing){ 
      audioTrack.write(music, 0, musicLength); 
     } 

     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 

} 


public void setFileName(File fileName) { 
    this.fileName = fileName; 
} 

public File getFileName() { 
    return fileName; 
} 

public void setPlaying(boolean playing) { 
    this.playing = playing; 
} 

public boolean isPlaying() { 
    return playing; 
} 

}

+0

감사 기록 ​​WAV 파일을 재생 내 클래스입니다! 이것을 시도 할 것이다. 나는 당신처럼 AudioTrack을 쓰레드 콜백에 ​​만들지 않을 것이다. 그게 치료법이라고 생각합니다 (나머지 코드는 내가 가지고있는 것과 거의 동일합니다). 그러면 두 AudioTrack의 "토글 (toggle)"이 서로를 막고있는 이유를 설명 할 수 있습니다. – BTR

+0

이것이 효과가 있는지 알려주세요. 나 또한 모든 스레드 관리를 할 다른 클래스에 싸여있다. 그런 다음 스레드 관리자를 호출하고 스트림 녹화 또는 재생을위한 스레딩에 대해 걱정할 필요가 없습니다. – DeliveryNinja

+2

그것보다 조금 더 많았지 만, 진짜 열쇠는 스레드 내부에 AudioTrack을 생성하고있었습니다. 나는 "장치"클래스의 별도의 일종을 가지고있어서 템포, 볼륨 등을 제어 할 수있었습니다. 파일을 읽고 그것을 하나의 스레드에서 모두 수행하는 클래스에 결합하면 좋은 결과를 얻을 수 있습니다. 지금 내 옵티머스 (600mHz)에서 DJ를하고 있습니다. :) – BTR