Я новичок в Android. Я разрабатываю приложение, которое использует AudioRecorder
и AudioTrack
для записи и воспроизведения. В дополнение к этому, я пытаюсь читать и отображать амплитудные значения записанного звука.Аудиодорожка в Android не работает
Вот мой класс
public class MainActivity extends AppCompatActivity {
private static final String TAG = "RecordSound";
private int BufferSize;
byte[] buffer = new byte[BufferSize];
/* AudioRecord and AudioTrack Object */
private AudioRecord record = null;
private AudioTrack track = null;
/* Audio Configuration */
private int sampleRate = 8000;
private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private boolean isRecording = true;
private Thread recordingThread = null;
private double lastLevel = 0;
private Thread thread;
private static final int SAMPLE_DELAY = 75;
MediaPlayer mediaPlayer;
RelativeLayout layout;
private ImageView tankHolder;
TextView text;
Button play;
String filename;
final Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tankHolder = (ImageView)findViewById(R.id.tankHolder);
text=(TextView)findViewById(R.id.result_text);
layout=(RelativeLayout)findViewById(R.id.linear);
play=(Button)findViewById(R.id.btnStartPlay);
try {
BufferSize = AudioRecord.getMinBufferSize(sampleRate,
channelConfig, audioFormat);
}catch (Exception e){
e.printStackTrace();
}
}
@Override
protected void onResume() {
super.onResume();
//calling MediaPlayer for alarmtone when the tank is almost full
mediaPlayer = MediaPlayer.create(this, R.raw.tone);
startRecording();
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
stopRecording();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private void stopRecording() throws IOException{
if (null != record) {
isRecording = false;
record.stop();
record.release();
record = null;
recordingThread = null;
mHandler.post(runRecord);
mediaPlayer.stop();
mediaPlayer.release();
}
}
final Runnable runRecord=new Runnable() {
@Override
public void run() {
text.setText("working");
try {
PlayShortAudioFileViaAudioTrack("/sdcard/recorded.pcm");
} catch (IOException e) {
e.printStackTrace();
}
}
};
private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException{
// We keep temporarily filePath globally as we have only two sample sounds now..
if (filePath==null)
return;
//Reading the file..
File file = new File(filePath); // for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"
byte[] byteData = new byte[(int) file.length()];
Log.d(TAG, (int) file.length()+"");
FileInputStream in = null;
try {
in = new FileInputStream(file);
in.read(byteData);
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Set and push to audio track..
int intSize = android.media.AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
Log.d(TAG, intSize+"");
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, intSize, AudioTrack.MODE_STREAM);
at.play();
// Write the byte array to the track
at.write(byteData, 0, byteData.length);
at.stop();
at.release();
}
private void startRecording()
{
record = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
channelConfig, audioFormat, BufferSize);
if (AudioRecord.STATE_INITIALIZED == record.getState())
record.startRecording();
isRecording = true;
/* Run a thread for Recording */
recordingThread = new Thread(new Runnable() {
@Override
public void run() {
writeAudioDataToFile();
}
},"AudioRecorder Thread");
recordingThread.start();
thread = new Thread(new Runnable() {
public void run() {
while(thread != null && !thread.isInterrupted()){
//Let's make the thread sleep for a the approximate sampling time
try{
Thread.sleep(SAMPLE_DELAY);}catch(InterruptedException ie){ie.printStackTrace();}
readAudioBuffer();//After this call we can get the last value assigned to the lastLevel variable
runOnUiThread(new Runnable() {
@Override
public void run() {
if(lastLevel >= 7 && lastLevel <= 15){
text.setTextColor(getResources().getColor(R.color.Blue));
layout.setBackgroundColor(Color.RED);
tankHolder.setImageResource(R.drawable.ftank);
if (!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
text.setText(String.valueOf(lastLevel));
}else
if(lastLevel > 50 && lastLevel <= 100){
text.setText(String.valueOf(lastLevel));
text.setTextColor(getResources().getColor(R.color.Orange));
layout.setBackgroundColor(Color.WHITE);
tankHolder.setImageResource(R.drawable.htank);
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
}else
if(lastLevel > 100 && lastLevel <= 170){
text.setText(String.valueOf(lastLevel));
text.setTextColor(getResources().getColor(R.color.Yellow));
layout.setBackgroundColor(Color.WHITE);
tankHolder.setImageResource(R.drawable.qtank);
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
}
if(lastLevel > 170){
text.setText(String.valueOf(lastLevel));
text.setTextColor(getResources().getColor(R.color.Blue));
layout.setBackgroundColor(Color.WHITE);
tankHolder.setImageResource(R.drawable.qtank);
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
}
}
});
}
}
},"AudioRecorder Thread");
thread.start();
}
private void writeAudioDataToFile()
{
byte data[] = new byte[BufferSize];
/* Record audio to following file */
String filePath = "/sdcard/recorded.pcm";
filename = Environment.getExternalStorageDirectory().getAbsolutePath();
filename +="/audiofile.pcm";
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int read_bytes = 0;
if(null != os){
while(isRecording)
{
read_bytes = record.read(data, 0, BufferSize);
if(AudioRecord.ERROR_INVALID_OPERATION != read_bytes){
try {
os.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void readAudioBuffer() {
try {
short[] buffer = new short[BufferSize];
int bufferReadResult = 1;
if (record != null) {
// Sense the voice...
bufferReadResult = record.read(buffer, 0, BufferSize);
double sumLevel = 0;
for (int i = 0; i < bufferReadResult; i++) {
sumLevel += buffer[i];
}
lastLevel = Math.abs((sumLevel/bufferReadResult));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Если я бегу, мой runOnUiThread(new Runnable() {
работает и воспроизведения нажатием кнопки, записанный звук не воспроизводится. Если я удалю runOnUiThread(new Runnable() {
, тогда нажмите кнопку воспроизведения, записанный звук будет воспроизводиться без проблем. Итак, я думаю, что проблема связана с потоками, и я попытался реализовать класс обработчика, но я его не получаю.
Я могу записать звук и воспроизвести его, если я не буду использовать runOnUiThread (новый Runnable() {thread.) Так что я хочу, чтобы ответ включал этот поток. –