Android Audio 系统的主要内容:

  • AudioManager:这个主要是用来管理Audio系统的,需要考虑整个系统上声音的策略问题,例如来电话铃声,短信铃声等,主要是策略上的问题。
  • AudioTrack:这个主要是用来播放声音的
  • AudioRecord:这个主要是用来录音的

当前分析AudioTrack的文章较多,先以AudioTrack为例进行分析。

JAVA层的AudioTrack class:framework\base\media\java\android\media\AudioTrack.java中。

AudioTrack的使用方法实例:

 1 //根据采样率,采样精度,单双声道来得到frame的大小。
 2 int bufsize = AudioTrack.getMinBufferSize(8000,//每秒8K个点
 3 AudioFormat.CHANNEL_CONFIGURATION_STEREO,//双声道
 4 AudioFormat.ENCODING_PCM_16BIT);//一个采样点16比特-2个字节
 5 //注意,按照数字音频的知识,这个算出来的是一秒钟buffer的大小。
 6 //创建AudioTrack
 7 AudioTrack trackplayer = new AudioTrack(AudioManager.STREAM_MUSIC, 8000,
 8 AudioFormat.CHANNEL_CONFIGURATION_ STEREO,
 9 AudioFormat.ENCODING_PCM_16BIT,bufsize,AudioTrack.MODE_STREAM);//
10 trackplayer.play() ;//开始
11 trackplayer.write(bytes_pkg, 0, bytes_pkg.length) ;//往track中写数据
12 ….
13 trackplayer.stop();//停止播放
14 trackplayer.release();//释放底层资源。

  AudioTrack.MODE_STREAMAudioTrack中有MODE_STATIC和MODE_STREAM两种分类。STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样,应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到audiotrack。这种方式的坏处就是总是在JAVA层和Native层交互,效率损失较大。而STATIC的意思是一开始创建的时候,就把音频数据放到一个固定的buffer,然后直接传给audiotrack,后续就不用一次次得write了。AudioTrack会自己播放这个buffer中的数据。这种方法对于铃声等内存占用较小,延时要求较高的声音来说很适用。

  StreamType:这个在构造AudioTrack的第一个参数中使用。这个参数和Android中的AudioManager有关系,涉及到手机上的音频管理策略。Android将系统的声音分为以下几类常见的(未写全):

  • STREAM_ALARM:警告声
  • STREAM_MUSCI:音乐声,例如music等
  • STREAM_RING:铃声
  • STREAM_SYSTEM:系统声音
  • STREAM_VOCIE_CALL:电话声音

  为什么要分这么多呢?以前在台式机上开发的时候很少知道有这么多的声音类型,不过仔细思考下,发现这样做是有道理的。例如你在听music的时候接到电话,这个时候music播放肯定会停止,此时你只能听到电话,如果你调节音量的话,这个调节肯定只对电话起作用。当电话打完了,再回到music,你肯定不用再调节音量了。其实系统将这几种声音的数据分开管理,所以,这个参数对AudioTrack来说,它的含义就是告诉系统,我现在想使用的是哪种类型的声音,这样系统就可以对应管理他们了。

  从AudioTrack的使用实例来逐个分析其中用到的方法,首先是getMinBufferSize:

  getMinBufferSize

/**
     * Returns the minimum buffer size required for the successful creation of an AudioTrack
     * object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't
     * guarantee a smooth playback under load, and higher values should be chosen according to
     * the expected frequency at which the buffer will be refilled with additional data to play.
     * For example, if you intend to dynamically set the source sample rate of an AudioTrack
     * to a higher value than the initial source sample rate, be sure to configure the buffer size
     * based on the highest planned sample rate.
     * @param sampleRateInHz the source sample rate expressed in Hz.
     * @param channelConfig describes the configuration of the audio channels.
     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
     * @param audioFormat the format in which the audio data is represented.
     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
     *   {@link AudioFormat#ENCODING_PCM_8BIT}
     * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
     *   or {@link #ERROR} if unable to query for output properties,
     *   or the minimum buffer size expressed in bytes.
     */
    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
        int channelCount = 0;
        switch(channelConfig) {
        case AudioFormat.CHANNEL_OUT_MONO:
        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
            channelCount = 1;
            break;
        case AudioFormat.CHANNEL_OUT_STEREO:
        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
            channelCount = 2;
            break;
        default:
            if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
                // input channel configuration features unsupported channels
                loge("getMinBufferSize(): Invalid channel configuration.");
                return ERROR_BAD_VALUE;
            } else {
                channelCount = Integer.bitCount(channelConfig);
            }
        }
      //目前只支持PCM8和PCM16精度的音频
        if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)
            && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
            loge("getMinBufferSize(): Invalid audio format.");
            return ERROR_BAD_VALUE;
        }
     //ft,对采样频率也有要求,太低或太高都不行,人耳分辨率在20HZ到40KHZ之间
        // sample rate, note these values are subject to change
        if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {
            loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
            return ERROR_BAD_VALUE;
        }
     //调用native函数
        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
        if (size <= 0) {
            loge("getMinBufferSize(): error querying hardware");
            return ERROR;
        }
        else {
            return size;
        }
    }
View Code

相关文章: