• android音乐柱状频谱实现


    原文地址:http://blog.csdn.net/caryee89/article/details/6935237


    注意android2.3以后才可用,主要用到这个类Visualizer,这个源码其实是apiDemos中一个例子,但例子中实现的是两种中的波形显示,而不是频谱显示,

    原文博主实现了另一种频谱显示,并分享出来,精神可嘉。我做了些修改,使稍微好看了些,继续分享。


    官方文档解释:

    public int getFft (byte[] fft)

    Since: API Level 9

    Returns a frequency capture of currently playing audio content.

    This method must be called when the Visualizer is enabled.

    The capture is an 8-bit magnitude

     FFT, the frequency range covered being 0 (DC) to half of the sampling rate returned by getSamplingRate(). The capture returns the real and imaginary parts of a number of frequency points equal to half of the capture size plus one.

    Note: only the real part is returned for the first point (DC) and the last point (sampling frequency / 2).

    The layout in the returned byte array is as follows:

    • n is the capture size returned by getCaptureSize()
    • Rfk, Ifk are respectively the real and imaginary parts of the kth frequency component
    • If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is: (k*Fs)/(n/2),---------->黄色背景为实部,其他的为虚部
    Index

    0

    1

    2

    3

    4

    5

    ...

    n - 2

    n - 1

    Data

    Rf0

    Rf(n/2)

    Rf1

    If1

    Rf2

    If2

    ...

    Rf(n-1)/2

    If(n-1)/2

    Parameters
    fft array of bytes where the FFT should be returned
    Returns
    实部和虚部的平方和就是振幅的平方,因为是byte类型,所以最大值是127。

    对原文的代码做了一些修改,使更好看一些,代码中用到的歌曲谁要用到,自己重新放一首就行,代码如下:

    [java] view plaincopy
    1. /* 
    2.  * Copyright (C) 2010 The Android Open Source Project 
    3.  * 
    4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
    5.  * you may not use this file except in compliance with the License. 
    6.  * You may obtain a copy of the License at 
    7.  * 
    8.  *      http://www.apache.org/licenses/LICENSE-2.0 
    9.  * 
    10.  * Unless required by applicable law or agreed to in writing, software 
    11.  * distributed under the License is distributed on an "AS IS" BASIS, 
    12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    13.  * See the License for the specific language governing permissions and 
    14.  * limitations under the License. 
    15.  */  
    16.   
    17. package com.AudioFx;  
    18.   
    19. import android.app.Activity;  
    20. import android.content.Context;  
    21. import android.graphics.Canvas;  
    22. import android.graphics.Color;  
    23. import android.graphics.Paint;  
    24. import android.graphics.Rect;  
    25. import android.media.AudioManager;  
    26. import android.media.MediaPlayer;  
    27. import android.media.audiofx.Equalizer;  
    28. import android.media.audiofx.Visualizer;  
    29. import android.os.Bundle;  
    30. import android.util.Log;  
    31. import android.view.Gravity;  
    32. import android.view.View;  
    33. import android.view.ViewGroup;  
    34. import android.view.WindowManager;  
    35. import android.widget.LinearLayout;  
    36. import android.widget.SeekBar;  
    37. import android.widget.TextView;  
    38.   
    39. public class AudioFxActivity extends Activity  
    40. {  
    41.     private static final String TAG = "AudioFxActivity";  
    42.   
    43.     private static final float VISUALIZER_HEIGHT_DIP = 160f;  
    44.   
    45.     private MediaPlayer mMediaPlayer;  
    46.     private Visualizer mVisualizer;  
    47.     private Equalizer mEqualizer;  
    48.   
    49.     private LinearLayout mLinearLayout;  
    50.     private VisualizerView mVisualizerView;  
    51.     private TextView mStatusTextView;  
    52.     private TextView mInfoView;  
    53.   
    54.     @Override  
    55.     public void onCreate(Bundle icicle)  
    56.     {  
    57.         super.onCreate(icicle);  
    58.           
    59.         mStatusTextView = new TextView(this);  
    60.   
    61.         mLinearLayout = new LinearLayout(this);  
    62.         mLinearLayout.setOrientation(LinearLayout.VERTICAL);  
    63.         mLinearLayout.addView(mStatusTextView);  
    64.   
    65.         setContentView(mLinearLayout);  
    66.   
    67.         // Create the MediaPlayer  
    68.         mMediaPlayer = MediaPlayer.create(this, R.raw.my_life);  
    69.         Log.d(TAG,  
    70.                 "MediaPlayer audio session ID: "  
    71.                         + mMediaPlayer.getAudioSessionId());  
    72.   
    73.         setupVisualizerFxAndUI();  
    74.         setupEqualizerFxAndUI();  
    75.   
    76.         // Make sure the visualizer is enabled only when you actually want to  
    77.         // receive data, and  
    78.         // when it makes sense to receive data.  
    79.         mVisualizer.setEnabled(true);  
    80.   
    81.         // When the stream ends, we don't need to collect any more data. We  
    82.         // don't do this in  
    83.         // setupVisualizerFxAndUI because we likely want to have more,  
    84.         // non-Visualizer related code  
    85.         // in this callback.  
    86.         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()  
    87.                 {  
    88.                     public void onCompletion(MediaPlayer mediaPlayer)  
    89.                     {  
    90.                         mVisualizer.setEnabled(false);  
    91.                         getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
    92.                         setVolumeControlStream(AudioManager.STREAM_SYSTEM);  
    93.                         mStatusTextView.setText("音乐播放完毕");  
    94.                     }  
    95.                 });  
    96.   
    97.         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);  
    98.         setVolumeControlStream(AudioManager.STREAM_MUSIC);  
    99.         mMediaPlayer.start();  
    100.         mStatusTextView.setText("播放音乐中....");  
    101.     }  
    102.   
    103.     private void setupEqualizerFxAndUI()  
    104.     {  
    105.         // Create the Equalizer object (an AudioEffect subclass) and attach it  
    106.         // to our media player,  
    107.         // with a default priority (0).  
    108.         mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId());  
    109.         mEqualizer.setEnabled(true);  
    110.   
    111.         TextView eqTextView = new TextView(this);  
    112.         eqTextView.setText("均衡器:");  
    113.         mLinearLayout.addView(eqTextView);  
    114.   
    115.         short bands = mEqualizer.getNumberOfBands();  
    116.   
    117.         final short minEQLevel = mEqualizer.getBandLevelRange()[0];  
    118.         final short maxEQLevel = mEqualizer.getBandLevelRange()[1];  
    119.   
    120.         for (short i = 0; i < bands; i++)  
    121.         {  
    122.             final short band = i;  
    123.   
    124.             TextView freqTextView = new TextView(this);  
    125.             freqTextView.setLayoutParams(new ViewGroup.LayoutParams(  
    126.                     ViewGroup.LayoutParams.FILL_PARENT,  
    127.                     ViewGroup.LayoutParams.WRAP_CONTENT));  
    128.             freqTextView.setGravity(Gravity.CENTER_HORIZONTAL);  
    129.             freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000)  
    130.                     + " Hz");  
    131.             mLinearLayout.addView(freqTextView);  
    132.   
    133.             LinearLayout row = new LinearLayout(this);  
    134.             row.setOrientation(LinearLayout.HORIZONTAL);  
    135.   
    136.             TextView minDbTextView = new TextView(this);  
    137.             minDbTextView.setLayoutParams(new ViewGroup.LayoutParams(  
    138.                     ViewGroup.LayoutParams.WRAP_CONTENT,  
    139.                     ViewGroup.LayoutParams.WRAP_CONTENT));  
    140.             minDbTextView.setText((minEQLevel / 100) + " dB");  
    141.   
    142.             TextView maxDbTextView = new TextView(this);  
    143.             maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams(  
    144.                     ViewGroup.LayoutParams.WRAP_CONTENT,  
    145.                     ViewGroup.LayoutParams.WRAP_CONTENT));  
    146.             maxDbTextView.setText((maxEQLevel / 100) + " dB");  
    147.   
    148.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(  
    149.                     ViewGroup.LayoutParams.FILL_PARENT,  
    150.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
    151.             layoutParams.weight = 1;  
    152.             SeekBar bar = new SeekBar(this);  
    153.             bar.setLayoutParams(layoutParams);  
    154.             bar.setMax(maxEQLevel - minEQLevel);  
    155.             bar.setProgress(mEqualizer.getBandLevel(band));  
    156.   
    157.             bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()  
    158.             {  
    159.                 public void onProgressChanged(SeekBar seekBar, int progress,  
    160.                         boolean fromUser)  
    161.                 {  
    162.                     mEqualizer.setBandLevel(band, (short) (progress + minEQLevel));  
    163.                 }  
    164.   
    165.                 public void onStartTrackingTouch(SeekBar seekBar)  
    166.                 {  
    167.                 }  
    168.   
    169.                 public void onStopTrackingTouch(SeekBar seekBar)  
    170.                 {  
    171.                 }  
    172.             });  
    173.   
    174.             row.addView(minDbTextView);  
    175.             row.addView(bar);  
    176.             row.addView(maxDbTextView);  
    177.   
    178.             mLinearLayout.addView(row);  
    179.         }  
    180.     }  
    181.   
    182.     private void setupVisualizerFxAndUI()  
    183.     {  
    184.         mVisualizerView = new VisualizerView(this);  
    185.         mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams(  
    186.                 ViewGroup.LayoutParams.FILL_PARENT,  
    187.                 (int) (VISUALIZER_HEIGHT_DIP * getResources()  
    188.                         .getDisplayMetrics().density)));  
    189.         mLinearLayout.addView(mVisualizerView);  
    190.   
    191.         mInfoView = new TextView(this);  
    192.         String infoStr = "";  
    193.           
    194.         int[] csr = Visualizer.getCaptureSizeRange();  
    195.         if(csr != null)  
    196.         {  
    197.             String csrStr = "CaptureSizeRange: ";  
    198.             for(int i = 0; i < csr.length; i ++)  
    199.             {  
    200.                 csrStr += csr[i];  
    201.                 csrStr +=" ";  
    202.             }  
    203.             infoStr += csrStr;  
    204.         }  
    205.           
    206.         final int maxCR = Visualizer.getMaxCaptureRate();  
    207.           
    208.         infoStr = infoStr + " MaxCaptureRate: " + maxCR;  
    209.           
    210.         mInfoView.setText(infoStr);  
    211.         mLinearLayout.addView(mInfoView);  
    212.           
    213.         mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());  
    214.         mVisualizer.setCaptureSize(256);  
    215.         mVisualizer.setDataCaptureListener(  
    216.                 new Visualizer.OnDataCaptureListener()  
    217.                 {  
    218.                     public void onWaveFormDataCapture(Visualizer visualizer,  
    219.                             byte[] bytes, int samplingRate)  
    220.                     {  
    221.                         mVisualizerView.updateVisualizer(bytes);  
    222.                     }  
    223.   
    224.                     public void onFftDataCapture(Visualizer visualizer,  
    225.                             byte[] fft, int samplingRate)  
    226.                     {  
    227.                         mVisualizerView.updateVisualizer(fft);  
    228.                     }  
    229.                 }, maxCR / 2falsetrue);  
    230.     }  
    231.   
    232.     @Override  
    233.     protected void onPause()  
    234.     {  
    235.         super.onPause();  
    236.   
    237.         if (isFinishing() && mMediaPlayer != null)  
    238.         {  
    239.             mVisualizer.release();  
    240.             mEqualizer.release();  
    241.             mMediaPlayer.release();  
    242.             mMediaPlayer = null;  
    243.         }  
    244.     }  
    245.       
    246.     /** 
    247.      * A simple class that draws waveform data received from a 
    248.      * {@link Visualizer.OnDataCaptureListener#onWaveFormDataCapture } 
    249.      */  
    250.     class VisualizerView extends View  
    251.     {  
    252.         private byte[] mBytes;  
    253.         private float[] mPoints;  
    254.         private Rect mRect = new Rect();  
    255.   
    256.         private Paint mForePaint = new Paint();  
    257.         private int mSpectrumNum = 48;  
    258.         private boolean mFirst = true;  
    259.   
    260.         public VisualizerView(Context context)  
    261.         {  
    262.             super(context);  
    263.             init();  
    264.         }  
    265.   
    266.         private void init()  
    267.         {  
    268.             mBytes = null;  
    269.   
    270.             mForePaint.setStrokeWidth(8f);  
    271.             mForePaint.setAntiAlias(true);  
    272.             mForePaint.setColor(Color.rgb(0128255));  
    273.         }  
    274.   
    275.         public void updateVisualizer(byte[] fft)  
    276.         {  
    277.             if(mFirst )  
    278.             {  
    279.                 mInfoView.setText(mInfoView.getText().toString() + " CaptureSize: " + fft.length);  
    280.                 mFirst = false;  
    281.             }  
    282.               
    283.               
    284.             byte[] model = new byte[fft.length / 2 + 1];  //
    285.   
    286.             model[0] = (byteMath.abs(fft[0]);
        
    287.             for (int i = 2, j = 1; j < mSpectrumNum;)  
    288.             {  
    289.                 model[j] = (byteMath.hypot(fft[i], fft[i + 1]);
      //函数用法:java.lang.Math.hypot(double x, double y) 返回sqrt(x2 +y2
    290.                 i += 2;  
    291.                 j++;  
    292.             }  
    293.             mBytes = model;  
    294.             invalidate();
        //绘制该视图
    295.         }  
    296.   
    297.         @Override  
    298.         protected void onDraw(Canvas canvas)  
    299.         {  
    300.             super.onDraw(canvas);  
    301.   
    302.             if (mBytes == null)  
    303.             {  
    304.                 return;  
    305.             }  
    306.   
    307.             if (mPoints == null || mPoints.length
       < mBytes
      .length * 4)  
    308.             {  
    309.                 mPoints = new float[mBytes.length * 4
      ];  
    310.             }  
    311.   
    312.             mRect.set(00, getWidth(), getHeight());
      //表示一个矩阵,由四条边的坐标组成  
    313.   
    314.             //绘制波形  
    315.             // for (int i = 0; i < mBytes.length - 1; i++) {  
    316.             // mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1);  
    317.             // mPoints[i * 4 + 1] = mRect.height() / 2  
    318.             // + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128;  
    319.             // mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1);  
    320.             // mPoints[i * 4 + 3] = mRect.height() / 2  
    321.             // + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128;  
    322.             // }  
    323.               
    324.             //绘制频谱  
    325.             final int baseX = mRect.width()/mSpectrumNum;  
    326.             final int height = mRect.height();  
    327.   
    328.             for (int i = 0; i < mSpectrumNum
       ; i++)  
    329.             {  
    330.                 if (mBytes[i] < 0)  
    331.                 {  
    332.                     mBytes[i] = 127;  
    333.                 }  
    334.                   
    335.                 final int xi = baseX*i + baseX/2;  
    336.                   
    337.                 mPoints[i * 4] = xi;  
    338.                 mPoints[i * 4 + 1] = height;  
    339.                   
    340.                 mPoints[i * 4 + 2] = xi;  
    341.                 mPoints[i * 4 + 3] = height - mBytes[i];  
    342.             }  
    343.   
    344.             canvas.drawLines(mPoints, mForePaint);  
    345.         }  
    346.     }  
    347. }  

    有关画图工具的使用方法:

    2、多条直线

    void drawLines (float[] pts, Paint paint)
    void drawLines (float[] pts, int offset, int count, Paint paint)

    参数:pts:是点的集合,大家下面可以看到,这里不是形成连接线,而是每两个点形成一条直线,pts的组织方式为{x1,y1,x2,y2,x3,y3,……}

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
    1. Paint paint=new Paint();  
    2. paint.setColor(Color.RED);  //设置画笔颜色      
    3. paint.setStyle(Style.FILL);//设置填充样式   
    4. paint.setStrokeWidth(5);//设置画笔宽度  
    5.   
    6. float []pts={10,10,100,100,200,200,400,400};  
    7. canvas.drawLines(pts, paint);  

    (上面有四个点:(10,10)、(100,100),(200,200),(400,400)),两两连成一条直线;


    运行效果如下:

  • 相关阅读:
    flash
    应用缓存
    音频和视频
    拖拽借口
    地理定位接口
    表单元素
    jquery常见用法
    jquery ajax 模板
    Ubuntu下Lucene环境搭配
    小絮叨
  • 原文地址:https://www.cnblogs.com/sowhat4999/p/4439832.html
Copyright © 2020-2023  润新知