• android音乐柱状频谱实现


    from: http://blog.csdn.net/topgun38/article/details/7663849

     

     

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

     

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

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

     

    官方文档解释:

     

    public int getFft (byte[] fft)

    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.     private static final String TAG = "AudioFxActivity"
    41.  
    42.     private static final float VISUALIZER_HEIGHT_DIP = 160f; 
    43.  
    44.     private MediaPlayer mMediaPlayer; 
    45.     private Visualizer mVisualizer; 
    46.     private Equalizer mEqualizer; 
    47.  
    48.     private LinearLayout mLinearLayout; 
    49.     private VisualizerView mVisualizerView; 
    50.     private TextView mStatusTextView; 
    51.     private TextView mInfoView; 
    52.  
    53.     @Override 
    54.     public void onCreate(Bundle icicle) 
    55.     { 
    56.         super.onCreate(icicle); 
    57.          
    58.         mStatusTextView = new TextView(this); 
    59.  
    60.         mLinearLayout = new LinearLayout(this); 
    61.         mLinearLayout.setOrientation(LinearLayout.VERTICAL); 
    62.         mLinearLayout.addView(mStatusTextView); 
    63.  
    64.         setContentView(mLinearLayout); 
    65.  
    66.         // Create the MediaPlayer 
    67.         mMediaPlayer = MediaPlayer.create(this, R.raw.my_life); 
    68.         Log.d(TAG, 
    69.                 "MediaPlayer audio session ID: " 
    70.                         + mMediaPlayer.getAudioSessionId()); 
    71.  
    72.         setupVisualizerFxAndUI(); 
    73.         setupEqualizerFxAndUI(); 
    74.  
    75.         // Make sure the visualizer is enabled only when you actually want to 
    76.         // receive data, and 
    77.         // when it makes sense to receive data. 
    78.         mVisualizer.setEnabled(true); 
    79.  
    80.         // When the stream ends, we don't need to collect any more data. We 
    81.         // don't do this in 
    82.         // setupVisualizerFxAndUI because we likely want to have more, 
    83.         // non-Visualizer related code 
    84.         // in this callback. 
    85.         mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
    86.                 { 
    87.                     public void onCompletion(MediaPlayer mediaPlayer) 
    88.                     { 
    89.                         mVisualizer.setEnabled(false); 
    90.                         getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    91.                         setVolumeControlStream(AudioManager.STREAM_SYSTEM); 
    92.                         mStatusTextView.setText("音乐播放完毕"); 
    93.                     } 
    94.                 }); 
    95.  
    96.         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
    97.         setVolumeControlStream(AudioManager.STREAM_MUSIC); 
    98.         mMediaPlayer.start(); 
    99.         mStatusTextView.setText("播放音乐中...."); 
    100.     } 
    101.  
    102.     private void setupEqualizerFxAndUI() 
    103.     { 
    104.         // Create the Equalizer object (an AudioEffect subclass) and attach it 
    105.         // to our media player, 
    106.         // with a default priority (0). 
    107.         mEqualizer = new Equalizer(0, mMediaPlayer.getAudioSessionId()); 
    108.         mEqualizer.setEnabled(true); 
    109.  
    110.         TextView eqTextView = new TextView(this); 
    111.         eqTextView.setText("均衡器:"); 
    112.         mLinearLayout.addView(eqTextView); 
    113.  
    114.         short bands = mEqualizer.getNumberOfBands(); 
    115.  
    116.         final short minEQLevel = mEqualizer.getBandLevelRange()[0]; 
    117.         final short maxEQLevel = mEqualizer.getBandLevelRange()[1]; 
    118.  
    119.         for (short i = 0; i < bands; i++) 
    120.         { 
    121.             final short band = i; 
    122.  
    123.             TextView freqTextView = new TextView(this); 
    124.             freqTextView.setLayoutParams(new ViewGroup.LayoutParams( 
    125.                     ViewGroup.LayoutParams.FILL_PARENT, 
    126.                     ViewGroup.LayoutParams.WRAP_CONTENT)); 
    127.             freqTextView.setGravity(Gravity.CENTER_HORIZONTAL); 
    128.             freqTextView.setText((mEqualizer.getCenterFreq(band) / 1000
    129.                     + " Hz"); 
    130.             mLinearLayout.addView(freqTextView); 
    131.  
    132.             LinearLayout row = new LinearLayout(this); 
    133.             row.setOrientation(LinearLayout.HORIZONTAL); 
    134.  
    135.             TextView minDbTextView = new TextView(this); 
    136.             minDbTextView.setLayoutParams(new ViewGroup.LayoutParams( 
    137.                     ViewGroup.LayoutParams.WRAP_CONTENT, 
    138.                     ViewGroup.LayoutParams.WRAP_CONTENT)); 
    139.             minDbTextView.setText((minEQLevel / 100) + " dB"); 
    140.  
    141.             TextView maxDbTextView = new TextView(this); 
    142.             maxDbTextView.setLayoutParams(new ViewGroup.LayoutParams( 
    143.                     ViewGroup.LayoutParams.WRAP_CONTENT, 
    144.                     ViewGroup.LayoutParams.WRAP_CONTENT)); 
    145.             maxDbTextView.setText((maxEQLevel / 100) + " dB"); 
    146.  
    147.             LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( 
    148.                     ViewGroup.LayoutParams.FILL_PARENT, 
    149.                     ViewGroup.LayoutParams.WRAP_CONTENT); 
    150.             layoutParams.weight = 1
    151.             SeekBar bar = new SeekBar(this); 
    152.             bar.setLayoutParams(layoutParams); 
    153.             bar.setMax(maxEQLevel - minEQLevel); 
    154.             bar.setProgress(mEqualizer.getBandLevel(band)); 
    155.  
    156.             bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() 
    157.             { 
    158.                 public void onProgressChanged(SeekBar seekBar, int progress, 
    159.                         boolean fromUser) 
    160.                 { 
    161.                     mEqualizer.setBandLevel(band, (short) (progress + minEQLevel)); 
    162.                 } 
    163.  
    164.                 public void onStartTrackingTouch(SeekBar seekBar) 
    165.                 { 
    166.                 } 
    167.  
    168.                 public void onStopTrackingTouch(SeekBar seekBar) 
    169.                 { 
    170.                 } 
    171.             }); 
    172.  
    173.             row.addView(minDbTextView); 
    174.             row.addView(bar); 
    175.             row.addView(maxDbTextView); 
    176.  
    177.             mLinearLayout.addView(row); 
    178.         } 
    179.     } 
    180.  
    181.     private void setupVisualizerFxAndUI() 
    182.     { 
    183.         mVisualizerView = new VisualizerView(this); 
    184.         mVisualizerView.setLayoutParams(new ViewGroup.LayoutParams( 
    185.                 ViewGroup.LayoutParams.FILL_PARENT, 
    186.                 (int) (VISUALIZER_HEIGHT_DIP * getResources() 
    187.                         .getDisplayMetrics().density))); 
    188.         mLinearLayout.addView(mVisualizerView); 
    189.  
    190.         mInfoView = new TextView(this); 
    191.         String infoStr = ""
    192.          
    193.         int[] csr = Visualizer.getCaptureSizeRange(); 
    194.         if(csr != null
    195.         { 
    196.             String csrStr = "CaptureSizeRange: "
    197.             for(int i = 0; i < csr.length; i ++) 
    198.             { 
    199.                 csrStr += csr[i]; 
    200.                 csrStr +=" "
    201.             } 
    202.             infoStr += csrStr; 
    203.         } 
    204.          
    205.         final int maxCR = Visualizer.getMaxCaptureRate(); 
    206.          
    207.         infoStr = infoStr + " MaxCaptureRate: " + maxCR; 
    208.          
    209.         mInfoView.setText(infoStr); 
    210.         mLinearLayout.addView(mInfoView); 
    211.          
    212.         mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId()); 
    213.         mVisualizer.setCaptureSize(256); 
    214.         mVisualizer.setDataCaptureListener( 
    215.                 new Visualizer.OnDataCaptureListener() 
    216.                 { 
    217.                     public void onWaveFormDataCapture(Visualizer visualizer, 
    218.                             byte[] bytes, int samplingRate) 
    219.                     { 
    220.                         mVisualizerView.updateVisualizer(bytes); 
    221.                     } 
    222.  
    223.                     public void onFftDataCapture(Visualizer visualizer, 
    224.                             byte[] fft, int samplingRate) 
    225.                     { 
    226.                         mVisualizerView.updateVisualizer(fft); 
    227.                     } 
    228.                 }, maxCR / 2, false, true); 
    229.     } 
    230.  
    231.     @Override 
    232.     protected void onPause() 
    233.     { 
    234.         super.onPause(); 
    235.  
    236.         if (isFinishing() && mMediaPlayer != null
    237.         { 
    238.             mVisualizer.release(); 
    239.             mEqualizer.release(); 
    240.             mMediaPlayer.release(); 
    241.             mMediaPlayer = null
    242.         } 
    243.     } 
    244.      
    245.     /**
    246.      * A simple class that draws waveform data received from a
    247.      * {@link Visualizer.OnDataCaptureListener#onWaveFormDataCapture }
    248.      */ 
    249.     class VisualizerView extends View 
    250.     { 
    251.         private byte[] mBytes; 
    252.         private float[] mPoints; 
    253.         private Rect mRect = new Rect(); 
    254.  
    255.         private Paint mForePaint = new Paint(); 
    256.         private int mSpectrumNum = 48
    257.         private boolean mFirst = true
    258.  
    259.         public VisualizerView(Context context) 
    260.         { 
    261.             super(context); 
    262.             init(); 
    263.         } 
    264.  
    265.         private void init() 
    266.         { 
    267.             mBytes = null
    268.  
    269.             mForePaint.setStrokeWidth(8f); 
    270.             mForePaint.setAntiAlias(true); 
    271.             mForePaint.setColor(Color.rgb(0, 128, 255)); 
    272.         } 
    273.  
    274.         public void updateVisualizer(byte[] fft) 
    275.         { 
    276.             if(mFirst ) 
    277.             { 
    278.                 mInfoView.setText(mInfoView.getText().toString() + " CaptureSize: " + fft.length); 
    279.                 mFirst = false
    280.             } 
    281.              
    282.              
    283.             byte[] model = new byte[fft.length / 2 + 1]; 
    284.  
    285.             model[0] = (byte) Math.abs(fft[0]); 
    286.             for (int i = 2, j = 1; j < mSpectrumNum;) 
    287.             { 
    288.                 model[j] = (byte) Math.hypot(fft[i], fft[i + 1]); 
    289.                 i += 2
    290.                 j++; 
    291.             } 
    292.             mBytes = model; 
    293.             invalidate(); 
    294.         } 
    295.  
    296.         @Override 
    297.         protected void onDraw(Canvas canvas) 
    298.         { 
    299.             super.onDraw(canvas); 
    300.  
    301.             if (mBytes == null
    302.             { 
    303.                 return
    304.             } 
    305.  
    306.             if (mPoints == null || mPoints.length < mBytes.length * 4
    307.             { 
    308.                 mPoints = new float[mBytes.length * 4]; 
    309.             } 
    310.  
    311.             mRect.set(0, 0, getWidth(), getHeight()); 
    312.  
    313.             //绘制波形 
    314.             // for (int i = 0; i < mBytes.length - 1; i++) { 
    315.             // mPoints[i * 4] = mRect.width() * i / (mBytes.length - 1); 
    316.             // mPoints[i * 4 + 1] = mRect.height() / 2 
    317.             // + ((byte) (mBytes[i] + 128)) * (mRect.height() / 2) / 128; 
    318.             // mPoints[i * 4 + 2] = mRect.width() * (i + 1) / (mBytes.length - 1); 
    319.             // mPoints[i * 4 + 3] = mRect.height() / 2 
    320.             // + ((byte) (mBytes[i + 1] + 128)) * (mRect.height() / 2) / 128; 
    321.             // } 
    322.              
    323.             //绘制频谱 
    324.             final int baseX = mRect.width()/mSpectrumNum; 
    325.             final int height = mRect.height(); 
    326.  
    327.             for (int i = 0; i < mSpectrumNum ; i++) 
    328.             { 
    329.                 if (mBytes[i] < 0
    330.                 { 
    331.                     mBytes[i] = 127
    332.                 } 
    333.                  
    334.                 final int xi = baseX*i + baseX/2
    335.                  
    336.                 mPoints[i * 4] = xi; 
    337.                 mPoints[i * 4 + 1] = height; 
    338.                  
    339.                 mPoints[i * 4 + 2] = xi; 
    340.                 mPoints[i * 4 + 3] = height - mBytes[i]; 
    341.             } 
    342.  
    343.             canvas.drawLines(mPoints, mForePaint); 
    344.         } 
    345.     } 


    运行效果如下:

     

  • 相关阅读:
    [转载]Nginx 常见应用技术指南
    【转载】Memcached Tip 2:Session同步
    【转载】大规模网站架构实战之体系结构
    【转载】3种Nginx防盗链的方法
    poj2390
    poj2395
    poj2393
    poj2209
    poj2392
    爱我更多,好吗?
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4510973.html
Copyright © 2020-2023  润新知