Android multimedia development (5) ---- use Android audiotrack to play MP3 files

Source: Internet
Author: User

/*************************************** **************************************** *************
* Author: conowen @ Dazhong
* E-mail: conowen@hotmail.com
* Http://blog.csdn.net/conowen
* Note: This article is original and only used for learning and communication. For more information, indicate the author and its source.

**************************************** **************************************** ************/

1. Introduction to Android audiotrack

In Android, mediaplayer and audiotrack can be used to play audio. However, mediaplayer can play audio files in multiple formats, such as MP3 and AAC, wav, Ogg, and Midi. However, audiotrack can only play PCM data streams.

In fact, there is no difference between the two types. When playing audio, The mediaplayer still creates audiotrack on the framework layer, transmits the decoded PCM number to audiotrack, and then audio mixing is performed by audioflinger, transmit the audio to the hardware for playback. Playing with audiotrack only skips the decoding part of the mediaplayer. The core part of mediaplayer decoding is implemented based on opencore and supports common audio/video and image formats. codec uses the openmax interface for expansion. Therefore, if you use audiotrack to play MP3 files, you must add an audio decoder, such as libmad. Otherwise, only PCM data can be played, such as most audio files in WAV format.

Refer to the previous blog.

Http://blog.csdn.net/conowen/article/details/7727145

2. Insufficient mediaplayer

Mediaplayer provides five setdatasource methods, one of which can be used to set the start address and length of the file stream.

Public void setdatasource (filedescriptor FD, long offset, long length) since:
API Level 1

Sets the data source (filedescriptor) to use. the filedescriptor must be seekable (N. b. A localsocket is not seekable ). it is the caller's responsibility to close the file descriptor. it is safe to do so as soon as this call returns.

Parameters
FD The filedescriptor for the file you want to play
Offset The offset into the file where the data to be played starts, in bytes
Length The length in bytes of the data to be played
Throws
Illegalstateexception If it is called in an invalid state
Ioexception  
Illegalargumentexception  

However, it is helpless to play encrypted audio files in real time. Although some encrypted audio files can be solved by combining audiotrack with libmad.


3. Simple demo program

The following provides an audiotrack MP3 demo. MP3 is not encrypted and the decoding part is completed by libmad. (If you want to play an encrypted audio file, you can use libmad to decode the file stream .)

Directly paste the Code. The Code has been commented out.

@ Libmadactivity. Java

/** Author: conowen * Date: 2012.7.29 */package COM. conowen. libmad; import android. app. activity; import android. media. audioformat; import android. media. audiomanager; import android. media. audiotrack; import android. OS. bundle; import android. util. log; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. toast; public class libmadactivity extends Activity {private thread mthread; private short [] audiobuffer; private audiotrack maudiotrack; private button btnplay, btnpausebutton; private int samplerate; private int maudiominbufsize; private int ret; private nativemp3decoder mp3decoder; private Boolean mthreadflag; private string filepath = "/sdcard/test1_";/** called when the activity is first created. * // @ overridepublic void oncreate (bundle savedi Nstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); btnplay = (button) findviewbyid (R. id. buttonplay); btnpausebutton = (button) findviewbyid (R. id. buttonpause); mp3decoder = new nativemp3decoder (); ret = mp3decoder. initaudioplayer (filepath, 0); If (ret =-1) {log. I ("conowen", "couldn't open file'" + filepath + "'");} else {mthreadflag = true; initaudioplayer (); audiobuffer = New short [1024*1024]; mthread = new thread (New runnable () {@ overridepublic void run () {// todo auto-generated method stubwhile (mthreadflag) {If (maudiotrack. getplaystate ()! = Audiotrack. playstate_paused) {// *** obtain data from libmad ******/mp3decoder. getaudiobuf (audiobuffer, maudiominbufsize); maudiotrack. write (audiobuffer, 0, maudiominbufsize);} else {try {thread. sleep (1000);} catch (interruptedexception e) {// todo auto-generated catch blocke. printstacktrace () ;}}}}); mthread. start ();} btnplay. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// t Odo auto-generated method stubif (ret =-1) {log. I ("conowen", "couldn't open file" + filepath + "'"); toast. maketext (getapplicationcontext (), "couldn't open file '" + filepath + "'", toast. length_short ). show ();} else {If (maudiotrack. getplaystate () = audiotrack. playstate_stopped) {// mthreadflag = true; // The audio thread starts maudiotrack. play (); // mthread. start ();} else if (maudiotrack. getplaystate () = audiotra CK. playstate_paused) {// mthreadflag = true; // The audio thread starts maudiotrack. play ();} else {toast. maketext (getapplicationcontext (), "already in play", toast. length_short ). show () ;}}}); btnpausebutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// todo auto-generated method stubif (ret =-1) {log. I ("conowen", "couldn't open file" + filepath + "'"); toast. maketext (getapplicat Ioncontext (), "couldn't open file'" + filepath + "'", toast. length_short ). show ();} else {If (maudiotrack. getplaystate () = audiotrack. playstate_playing) {maudiotrack. pause ();} else {toast. maketext (getapplicationcontext (), "already stop", toast. length_short ). show () ;}}});} private void initaudioplayer () {// todo auto-generated method stubsamplerate = mp3decoder. getaudiosamplerate (); system. out. println ("Samplerate =" + samplerate); samplerate = samplerate/2; // the buffer size of the audio file in one second. maudiominbufsize = audiotrack. getminbuffersize (samplerate, audioformat. channel_configuration_stereo, audioformat. encoding_pcm_16bit); maudiotrack = new audiotrack (audiomanager. stream_music, // specify the type of the stream. // stream_alarm: warning sound // stream_musci: music sound, such as music. // stream_ring: ringtone/stream_system: system sound // stream_vocie_call: phone Voice samplerate, // set Audio Data Sampling Rate audioformat. channel_configuration_stereo, // set the output channel to dual-channel audioformat. encoding_pcm_16bit, // sets whether the audio data block is 8-bit or 16-bit maudiominbufsize, audiotrack. mode_stream); // set the mode type, which is set to stream type. // audiotrack contains mode_static and mode_stream. // Stream indicates that the data is written to audiotrack once by using write. // The disadvantage of this method is that the Java layer and the native layer constantly exchange data, resulting in high efficiency loss. // The static mode indicates that the audio data is stored in a fixed buffer when it is created at the beginning, and then directly transmitted to audiotrack. // No write operation is required in the future. Audiotrack automatically plays data in this buffer. // This method is suitable for small files such as ringtones .} Static {system. loadlibrary ("mad") ;}@ overrideprotected void ondestroy () {// todo auto-generated method stubsuper. ondestroy (); maudiotrack. stop (); maudiotrack. release (); // close and release the resource mthreadflag = false; // The audio thread suspends mp3decoder. closeaduiofile ();}}

@ Nativemp3decoder. Java

package com.conowen.libmad;public class NativeMP3Decoder {private int ret;public NativeMP3Decoder() {}public native int initAudioPlayer(String file,int StartAddr);public native int getAudioBuf(short[] audioBuffer, int numSamples);public native void closeAduioFile();public native int getAudioSamplerate();}

@ Main. xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >    <TextView      android:layout_width="fill_parent"     android:layout_height="wrap_content"     android:text="AudioTrack"    />          <Button      android:id = "@+id/buttonPlay"    android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="PLAY"    />        <Button      android:id = "@+id/buttonPause"    android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="PAUSE"    />       </LinearLayout>

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.