广

android开发

  • IOS开发
  • android开发
  • PHP编程
  • JavaScript
  • ASP.NET
  • ASP编程
  • JSP编程
  • Java编程
  • 易语言
  • Ruby编程
  • Perl编程
  • AJAX
  • 正则表达式
  • C语言
  • 编程开发

    Android音频可视化开发案例说明

    2018-04-03 22:30:42 次阅读 稿源:互联网
    广告
    Android 调用自带的录制音频程序
    Android中有自带的音频录制程序,我们可以通过指定一个Action MediaStore.Audio.Media.RECORD_SOUND_ACTION的Intent来
    启动它就可以了。然后在onActivityResult()方法中,获取Intent的Data,就是录制的音频对应的URI。
    java代码:
    代码如下:

    package eoe.demo;
    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.view.View;
    import android.widget.Toast;
    /**
    * 被实例演示如何调用Android自带的应用来完成Audio的录入
    * 其实很简单,我们需要指定一个MediaStore.Audio.Media.RECORD_SOUND_ACTION的Action来启动就可以
    * 返回的Data数据就是我们录制的音频的URI了
    *
    * 通过上面这种方式,灵活性不够高,我们可以利用MediaRecorder类来实现自己的音频录制程序
    * MediaRecorder既可以用来录制音频,也可以用来录制视频
    * 创建了一个MediaRecorder实例后,需要调用setAudioSource和setAudioEncoder来初始化
    * 通常情况下,在准备录制前,我们还需要调用setOutputFormat()方法来决定使用的音频格式,同时调用
    * setOutputFile()来指定存放录制内容的文件
    *
    * 这几个方法的调用顺序是:setAudioSource,setOutputFormat,setAudioEncoder,setOutputFile
    *
    *
    *
    * @author Administrator
    *
    */
    public class AudioRecordDemo extends Activity {
    public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.audio_record);
    }
    public void onActivityResult(int requestCode, int resultCode, Intent data){
    //super.onActivityResult(requestCode, resultCode, data);
    //这里我们就可以获取到刚刚录制的音频的Uri,可以进行播放等操作,这里显示返回的Uri
    if(resultCode == RESULT_OK){
    Uri audioPath = data.getData();
    Toast.makeText(this, audioPath.toString(), Toast.LENGTH_LONG).show();
    }
    }
    public void onClick(View v){
    int id = v.getId();
    switch(id){
    case R.id.btn1: //调用Android自带的音频录制应用
    Intent intent = new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
    startActivityForResult(intent, 0);
    break;
    case R.id.btn2:
    //通过MediaRecorder类来实现自己的音频录制程序
    Intent intent2 = new Intent();
    intent2.setClass(this, MyAudioRecord.class);
    startActivityForResult(intent2, 1);
    break;
    case R.id.btn3:
    //通过AudioRecord类实现自己的音频录制程序
    Intent intent3 = new Intent();
    intent3.setClass(this, MyAudioRecord2.class);
    startActivityForResult(intent3, 2);
    break;
    }
    }
    }

    Android 音频的介绍
    最近移植Android,当Android能够在设备上面运行之后,首先想到的是让音频设备跑起来。“没有声音,再好的戏也出不来”。本文简单介绍一下Android音频适配层。
    这个世界音频设备千变万化,Android也不可能为每种设备都提供支持。Android定义了一个框架,这个框架来适配底层的音频设备。该适配层的定义位于:
    Java代码:
    代码如下:

    hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h

    要想视频底层的音频设备必须要继承该文件中定义的AudioStreamOut,AudioStreamIn,AudioHardwareInterface等类,并实现createAudioHardware函数。
    下面我们看一下Android创建音频设备的代码,代码位于:
    Java代码:
    代码如下:

    frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp

    该文件有如下代码:
    Java代码:
    代码如下:

    AudioHardwareInterface* AudioHardwareInterface::create()
    {
    /*
    * FIXME: This code needs to instantiate the correct audio device
    * interface. For now - we use compile-time switches.
    */
    AudioHardwareInterface* hw = 0;
    char value[PROPERTY_VALUE_MAX];
    #ifdef GENERIC_AUDIO
    hw = new AudioHardwareGeneric();
    #else
    // 如果运行在仿真中——用这个模拟器
    if (property_get("ro.kernel.qemu", value, 0)) {
    LOGD("Running in emulation - using generic audio driver");
    hw = new AudioHardwareGeneric();
    }
    else {
    LOGV("Creating Vendor Specific AudioHardware");
    hw = createAudioHardware();
    }
    #endif
    if (hw->initCheck() != NO_ERROR) {
    LOGW("Using stubbed audio hardware. No sound will be produced.");
    delete hw;
    hw = new AudioHardwareStub();
    }
    #ifdef WITH_A2DP
    hw = new A2dpAudioInterface(hw);
    #endif
    #ifdef ENABLE_AUDIO_DUMP
    recorded in the file.
    LOGV("opening PCM dump interface");
    hw = new AudioDumpInterface(hw); // replace interface
    #endif
    return hw;
    }

    从代码中我们可以看出如果定义了GENERIC_AUDIO的宏,则会创建AudioHardwareGeneric,如果是模拟器的话,AudioHardwareGeneric会不能初始化,进而创建AudioHardwareStub。这两个类都是Audio设备的适配层,是Android默认提供的。模拟器都是用AudioHardwareStub,不会有声音输出。设备都是用AudioHardwareGeneric,因为默认GENERIC_AUDIO是设置的。
    一般我们只关心AudioHardwareGeneric实现,谁会去给模拟器去调试声音呢,反正我没这个闲心。首先说明一下这个音频适配层是Android自带的,可以保证你的音频设备正常运行,但是不能发挥设备的最佳性能。通过后面的描述你将会了解。AudioHardwareGeneric的定义位于:
    Java代码:
    代码如下:

    frameworks/base/libs/audioflinger/AudioHardwareGeneric.cpp

    上面就是eoe给我们介绍音频用途,如果有什么不明白的就多看看android的源码,这样有助与你对音频的理解。
    先看一下效果图
     
    代码如下:

    public class FFTActivity extends Activity implements OnClickListener{
    private Button button;
    private ImageView imageView;
    private int frequency = 8000;
    private int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    private RealDoubleFFT transformer;
    private int blockSize = 256;
    private boolean started = false;
    private Canvas canvas;
    private Paint paint;
    private Bitmap bitmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.fft);
    button = (Button) findViewById(R.id.fft_button);
    button.setOnClickListener(this);
    imageView = (ImageView) findViewById(R.id.fft_imageView);
    transformer = new RealDoubleFFT(blockSize);
    bitmap = Bitmap.createBitmap(256, 100, Bitmap.Config.ARGB_8888);
    canvas = new Canvas(bitmap);
    paint = new Paint();
    paint.setColor(Color.GREEN);
    imageView.setImageBitmap(bitmap);
    }
    private class RecordAudio extends AsyncTask<Void, double[], Void> {
    @Override
    protected Void doInBackground(Void... params) {
    int bufferSize = AudioRecord.getMinBufferSize(frequency,
    channelConfiguration, audioEncoding);
    AudioRecord audioRecord = new AudioRecord(
    MediaRecorder.AudioSource.MIC, frequency,
    channelConfiguration, audioEncoding, bufferSize);
    short[] buffer = new short[blockSize];
    double[] toTransform = new double[blockSize];
    audioRecord.startRecording();
    while (started) {
    //将record的数据 读到buffer中,但是我认为叫做write可能会比较合适些。
    int bufferResult = audioRecord.read(buffer, 0, blockSize);
    for (int i = 0; i < bufferResult; i++) {
    toTransform<i> = (double) buffer<i> / Short.MAX_VALUE;
    }
    transformer.ft(toTransform);
    publishProgress(toTransform);
    }
    audioRecord.stop();
    return null;
    }
    @Override
    protected void onProgressUpdate(double[]... values) {
    super.onProgressUpdate(values);
    canvas.drawColor(Color.BLACK);
    for (int i = 0; i < values[0].length; i++) {
    int x=i;
    int downy=(int)(100-(values[0]<i>)*10);
    int upy=100;
    canvas.drawLine(x, downy, x, upy, paint);
    }
    imageView.invalidate();
    }
    }
    @Override
    public void onClick(View v) {
    started=true;
    new RecordAudio().execute();
    }
    }

    android音频可视化的原理是使用离散傅里叶变换,但是数学不好的同学不要担心,有开源的java离散傅里叶变换的代码!!直接到www.netlib.org/fftpack/jfftpack.tgz,直接将里面javasource目录拖动到(ca目录)src即可!!

    一起学吧部分文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与一起学吧进行文章共享合作。

    广告
    广告
    广告