Use Android AudioTrack playing PCM

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/myvest/article/details/90731805

Brief introduction

AudioTrack the Android system resource management and playback of a single audio class, relatively simple, but note that it has only displays the decoded PCM data.

Of an audio file (such as MP3 files), how to use FFmpeg to decode get to PCM, previous articles have corresponding descriptions:
https://blog.csdn.net/myvest/article/details/89254452
use AudioTrack to play PCM before the data, we first decoded PCM data to be resampled, i.e., is converted to the specified format, and we will use AudioTrack playback format is fixed to. Resampling can refer to:
https://blog.csdn.net/myvest/article/details/89442000

Using the methods and API Introduction

AudioTrack used as follows:
1, Created:

public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
            int bufferSizeInBytes, int mode);

Parameter Description:
1) int streamType: specifies the type of sound is about to play for different types, Android's audio systems have different treatment (such as a different volume levels, different volume control, etc.), some of the common types are as follows, for music files, we use STREAM_MUSIC

  • STREAM_ALARM: warning sound
  • STREAM_MUSIC: music, such as music, etc.
  • STREAM_RING: Ringtones
  • STREAM_SYSTEM: sound system, for example, low tone, lock screen, sound, etc.
  • STREAM_VOCIE_CALL: Call Sound

Two AudioTrack data loading mode (MODE_STREAM and MODE_STATIC), corresponding to loading mode and the data type of the audio stream, corresponding to two completely different usage scenarios.

2) int sampleRateInHz: sampling rate
3) int channelConfig: audio channel corresponding to the layout, such as a stereo AudioFormat.CHANNEL_OUT_STEREO
. 4) int AudioFormat: audio format
5) int bufferSizeInBytes: buffer size
buffer size may be obtained by a function getMinBufferSize, pass the sampling rate, channel layout, audio format can be as follows:

public AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);

6) int mode: data loading mode (MODE_STREAM and MODE_STATIC), corresponding to the two modes used in two different scenarios

  • MODE_STREAM: In this mode, the write data is written again AudioTrack the audio. This is usually invoked by write system to write data to a similar file, but this way of working requires every user to copy data from Buffer to Buffer provided in the interior of the AudioTrack, which to some extent will the introduction of delay. To solve this problem, AudioTrack on the introduction of a second model.
  • MODE_STATIC: In this mode, just need to play before all of the data transmitted by a single call to write in the internal buffer AudioTrack, you do not have to follow the data transmission. This mode is suitable as ringtones This smaller footprint, higher latency requirements document. But it also has a shortcoming, which is a write data can not be too much, otherwise the system can not allocate enough memory to store all the data.

2, start:

public AudioTrack.play();

3, data injection:

public int write(byte[] audioData, int offsetInBytes, int sizeInBytes);

Relatively simple parameters, data, offset, size

4, stop:

public AudioTrack.stop();		

5, the release:

public   AudioTrack.release();

6, get status:
STATE_INITIALIZED and STATE_UNINITIALIZED would not have explained. STATE_NO_STATIC_DATA is an intermediate state, when MODE_STATIC mode, create AudioTrack, will first change into the state, the need to write data, will become STATE_INITIALIZED state. Non-STATE_INITIALIZED state were down play, then will throw an exception, so MODE_STATIC mode if there is no write is not enough to go play.

    /**
     * Returns the state of the AudioTrack instance. This is useful after the
     * AudioTrack instance has been created to check if it was initialized
     * properly. This ensures that the appropriate resources have been acquired.
     * @see #STATE_INITIALIZED
     * @see #STATE_NO_STATIC_DATA
     * @see #STATE_UNINITIALIZED
     */
    public int getState() {
        return mState;
    }

Examples

	private AudioTrack audioTrack = null;
	private static int sampleRateInHz = 44100;
	private static int channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
	private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
	private int bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);

	class processThread implements Runnable {
......省略
		public void run() {		    			
		    byte[] outBuf = new byte[DECODE_BUFFER_SIZE];
		    if(audioTrack == null){
				audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, channelConfig, audioFormat, bufferSize,
					AudioTrack.MODE_STREAM);
				if(audioTrack == null){
					mFFdec.decodeDeInit();			
					return ;
				}
		    }
		    try {
			   if ( audioTrack.getState() != AudioTrack.STATE_UNINITIALIZED) {
					audioTrack.play();
			   }
			   while(true){
				   int size = mFFdec.decodeFrame(outBuf);
				   if(size > 0){
						if(mFFdec.getMediaType() == mFFdec.MEDIA_TYPE_AUDIO){//audio
							audioTrack.write(outBuf, 0, size);
						}
				   }else{
				   		break;
				   }
			   }			   
			   if (audioTrack.getState() != AudioTrack.STATE_UNINITIALIZED) {
					audioTrack.stop();
					audioTrack.release();
			   }			   
		    }catch (Exception ex) {
				   ex.printStackTrace();
		    } catch (Throwable t) {
				   t.printStackTrace();
		    }		    
		    audioTrack = null;
		    mFFdec.decodeDeInit();
		}
	}

Guess you like

Origin blog.csdn.net/myvest/article/details/90731805