源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2020-08-03 22:42 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android音频可视化开发案例说明
[b]Android 调用自带的录制音频程序[/b] Android中有自带的音频录制程序,我们可以通过指定一个Action MediaStore.Audio.Media.RECORD_SOUND_ACTION的Intent来 启动它就可以了。然后在onActivityResult()方法中,获取Intent的Data,就是录制的音频对应的URI。 java代码:
[u]复制代码[/u] 代码如下:
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; } } }
[b]Android 音频的介绍[/b] 最近移植Android,当Android能够在设备上面运行之后,首先想到的是让音频设备跑起来。“没有声音,再好的戏也出不来”。本文简单介绍一下Android音频适配层。 这个世界音频设备千变万化,Android也不可能为每种设备都提供支持。Android定义了一个框架,这个框架来适配底层的音频设备。该适配层的定义位于: Java代码:
[u]复制代码[/u] 代码如下:
hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h
要想视频底层的音频设备必须要继承该文件中定义的AudioStreamOut,AudioStreamIn,AudioHardwareInterface等类,并实现createAudioHardware函数。 下面我们看一下Android创建音频设备的代码,代码位于: Java代码:
[u]复制代码[/u] 代码如下:
frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp
该文件有如下代码: Java代码:
[u]复制代码[/u] 代码如下:
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代码:
[u]复制代码[/u] 代码如下:
frameworks/base/libs/audioflinger/AudioHardwareGeneric.cpp
上面就是eoe给我们介绍音频用途,如果有什么不明白的就多看看android的源码,这样有助与你对音频的理解。 [b]先看一下效果图[/b]: [img]http://files.jb51.net/file_images/article/201212/20121228143547678.png[/img]  
[u]复制代码[/u] 代码如下:
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即可!!
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部