Android 音乐频谱实现

最近由于需要实现音乐频谱,所以今天就为大家普及一下。关于音乐频谱你需要了解数字信号处理的知识,尤其是FFT的知识。简单说就是把时域上连续的信号(波形)强度转换成离散的频域信号(频谱)。我理解波形就是信号的强度,或者说音响设备的输出的功率,功率高,音量就大。但是歌曲的曲调是不会变的,因为频谱是不会变的。

频谱反映的是这个这个音乐在某个连续时间段内,声音的震动频率。不知道理解的对不对。

本文的音乐频谱实现是仿照Android Api Demo 里的一个例子实现的,需要Android 2.3及以上系统,因为要用到Visualizer 类,这个类只在Android 2.3以上的API才支持。

首先实例化Visualizer,参数SessionId可以通过MediaPlayer的对象获得

	visualizer = new Visualizer(mPlayerInstance.getAudioSessionId());
接着设置需要转换的音乐内容长度,专业的说这就是采样,该采样值一般为2的指数倍,如64,128,256,512,1024。这里我设置了128,原因是长度越长,FFT算法运行时间更长。

	visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[0]);
然后为visualizer设置监听器,这样当Capture一段数据后,就会触发两个函数进行处理。设置监听函数为

	setDataCaptureListener(OnDataCaptureListener listener, rata,iswave,isfft )
参数解释:

rate, 表示采样的周期,即隔多久采样一次,联系前文就是隔多久采样128个数据,本文设置为512mHz更新一次

iswave,是波形信号

isfft,是FFT信号,表示是获取波形信号还是频域信号

OnDataCaptureListener,表监听函数,匿名内部类实现该接口,该接口需要实现两个函数

	onWaveFormDataCapture(Visualizer visualizer,byte[] waveform, int samplingRate) 

	public void onFftDataCapture(Visualizer visualizer,byte[] fft, int samplingRate) 
samplingRate是采样速率,即上文的rate值,512mHz。

其中两个byte[] waveform和byte[] fft数组,分别是获得波形数据和FFT的数据,该byte数组的大小即为之前设置的采样值大小128,获得数据如下图所示。

其中n为采样值,index 0 表示直流分量,Rf表示FFT计算后的实部,If表示FFT计算后的虚部。

如何计算出该频率,就是将FFT的实部和对应的虚部先各自平方再相加然后开方,简单说就是平方取模。

具体计算请看如下的代码。

	visualizer.setDataCaptureListener(
		new Visualizer.OnDataCaptureListener() {

			@Override
			public void onWaveFormDataCapture(Visualizer visualizer,
				byte[] waveform, int samplingRate) {

				// 这里添加获得数据的处理 byte[] 数组 更新出去,并画图。这里可以把这个
				// 数组传到RunOnMusic里去
				// visualView.updateVisualizer(waveform);

			}

			@Override
			public void onFftDataCapture(Visualizer visualizer,
				byte[] fft, int samplingRate) {
				byte[] model = new byte[fft.length / 2 + 1];
				model[0] = (byte) Math.abs(fft[1]);
				int j = 1;

				for (int i = 2; i < 18;) {
					model[j] = (byte) Math.hypot(fft[i], fft[i + 1]);
					i += 2;
					j++;
				}

				visualView.updateVisualizer(model);

			}
		}, Visualizer.getMaxCaptureRate() / 2, false, true);

	}

其中visualView是显示程序,updateVisulizer是将model获取的频谱值更新到要显示的view。

	
      protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		if (mBytes == null) {
		    return;
		}

		if (mPoints == null || mPoints.length < mBytes.length * 4) {
		
                    mPoints = new float[mBytes.length * 4];
                    mRect.set(0, 0, getWidth(), getHeight() - 50);
                 
                    for (int i = 0; i < 9; i++) {
	               
                        if (mBytes[i] < 0)
                            mBytes[i] = 127; 
                        
                        mPoints[i * 4] = mRect.width() * i / 9;
                        mPoints[i * 4 + 1] = mRect.height() / 2;
                        mPoints[i * 4 + 2] = mRect.width() * i / 9;
                        mPoints[i * 4 + 3] = 2 + mRect.height() / 2 + mBytes[i];
                    }
                    canvas.drawLines(mPoints, mForePaint);
                }

	}



  • 4
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 30
    评论
如果你想在Android应用程序中实现音乐频谱,可以使用Android的Media Player类来获取音频数据。然后,你可以使用FFT(快速傅里叶变换)算法将音频数据转换为频谱数据。最后,你可以使用Canvas和Paint类在屏幕上绘制频谱图。 以下是一个简单的实现方法: 1. 在你的Android应用程序中,创建一个MediaPlayer对象并设置音频资源: ```java MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.song); ``` 2. 创建一个Visualizer对象,并将其连接到MediaPlayer对象: ```java Visualizer visualizer = new Visualizer(mediaPlayer.getAudioSessionId()); visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); visualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() { @Override public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) { // 处理波形数据 } @Override public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) { // 处理FFT数据 } }, Visualizer.getMaxCaptureRate() / 2, true, true); visualizer.setEnabled(true); ``` 3. 在onFftDataCapture回调方法中,将FFT数据转换为频谱数据,然后绘制频谱图。以下是一个简单的FFT转换方法: ```java private void transformFFT(byte[] fft) { int[] buffer = new int[fft.length / 2]; for (int i = 0, j = 0; i < fft.length; i += 2, j++) { buffer[j] = (fft[i] & 0xFF) | (fft[i + 1] & 0xFF) << 8; } DoubleFFT_1D fftTransform = new DoubleFFT_1D(buffer.length); double[] fftData = new double[buffer.length * 2]; for (int i = 0; i < buffer.length; i++) { fftData[i * 2] = buffer[i]; } fftTransform.realForwardFull(fftData); // 处理FFT数据 } ``` 4. 在处理FFT数据后,可以使用Canvas和Paint绘制频谱图。以下是一个简单的绘图方法: ```java private void drawSpectrum(Canvas canvas, Paint paint, float[] spectrum) { float barWidth = (float) getWidth() / spectrum.length; float barHeight; float x = 0; for (int i = 0; i < spectrum.length; i++) { barHeight = (spectrum[i] + 128) * 2; canvas.drawRect(x, getHeight() - barHeight, x + barWidth, getHeight(), paint); x += barWidth + 1; } } ``` 以上是一个简单的实现方法,你可以根据实际需要进行调整和优化。
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值