中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

外貿(mào)網(wǎng)站制作百度純凈版首頁入口

外貿(mào)網(wǎng)站制作,百度純凈版首頁入口,網(wǎng)站建設(shè)規(guī)劃方案論文,奇信建設(shè)集團官方網(wǎng)站Visualizer 是使應(yīng)用程序能夠檢索當(dāng)前播放音頻的一部分以進行可視化。它不是錄音接口,僅返回部分低質(zhì)量的音頻內(nèi)容。但是,為了保護某些音頻數(shù)據(jù)的隱私,使用 Visualizer 需要 android.permission.RECORD_AUDIO權(quán)限。傳遞給構(gòu)造函數(shù)的音頻會話 …

? ? ? ? Visualizer 是使應(yīng)用程序能夠檢索當(dāng)前播放音頻的一部分以進行可視化。它不是錄音接口,僅返回部分低質(zhì)量的音頻內(nèi)容。但是,為了保護某些音頻數(shù)據(jù)的隱私,使用 Visualizer 需要 android.permission.RECORD_AUDIO權(quán)限。傳遞給構(gòu)造函數(shù)的音頻會話 ID 指示應(yīng)可視化哪些音頻內(nèi)容:

  • 如果會話為 0,則音頻輸出混合可視化
  • 如果會話不為 0,則顯示來自特定會話android.media.MediaPlayer或使用此音頻會話的音頻android.media.AudioTrack

可以捕獲兩種類型的音頻內(nèi)容表現(xiàn)形式:

  • 波形數(shù)據(jù):使用該getWaveForm(byte[])方法連續(xù)的8位(無符號)單聲道樣本
  • 頻率數(shù)據(jù):采用8位幅度FFTgetFft(byte[])方法

捕獲的長度可以通過分別調(diào)用getCaptureSize()setCaptureSize(int)方法來檢索或指定。捕獲大小必須是返回范圍內(nèi)的 2 的冪getCaptureSizeRange()。

1. 權(quán)限請求

需要在Manifest里面添加

 <uses-permission android:name="android.permission.RECORD_AUDIO" />

RECORD_AUDIOAndroid 6.0后需要動態(tài)請求權(quán)限

val audioPermission =ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)if (audioPermission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this,permissions,PERMISSION_REQUEST_CODE /* your request code */)}
2. 初始化Visualizer

首先初始化MediaPlayer,初始MediaPlayer是為了拿到audioSessionId

  MusicPlayHelper.init(application, object : IMusicPlayListener {override fun loadMusicFinish(boolean: Boolean, position: Int) {MusicPlayHelper.play()}})

初始化Visualizer,musicId就是上面的audioSessionId,如果傳0是全局改變,但是有可能會報錯。

   if (mVisualizer == null) {mVisualizer = Visualizer(musicId)}mVisualizer?.enabled = falsemVisualizer?.captureSize = Visualizer.getCaptureSizeRange()[1]mVisualizer?.setDataCaptureListener(captureListener,Visualizer.getMaxCaptureRate() / 2,true,true)// Enabled Visualizer and disable when we're done with the streammVisualizer?.enabled = true

setDataCaptureListener?為可視化對象設(shè)置采樣監(jiān)聽數(shù)據(jù)的回調(diào),setDataCaptureListener的參數(shù)作用如下:

listener:回調(diào)對象
rate:采樣的頻率,其范圍是0~Visualizer.getMaxCaptureRate(),此處設(shè)置為最大值一半。
waveform:是否獲取波形信息
fft:是否獲取快速傅里葉變換后的數(shù)據(jù)

OnDataCaptureListener中的兩個回調(diào)方法分別為:

onWaveFormDataCapture:波形數(shù)據(jù)回調(diào)
onFftDataCapture:傅里葉數(shù)據(jù)回調(diào),即頻率數(shù)據(jù)回調(diào)

3.設(shè)置Visualizer是否接收數(shù)據(jù)

enable為true正常接收,為false關(guān)閉

fun setVisualizerEnable(flag: Boolean) {mVisualizer?.enabled = flag
}
4. 釋放Visualizer

使用完需要調(diào)用release方法釋放

    fun release() {mVisualizer?.enabled = falsemVisualizer?.release()mVisualizer = null}

完整VisualizerView代碼

package com.example.knowledgemanagement.visualizerimport android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.media.audiofx.Visualizer
import android.media.audiofx.Visualizer.OnDataCaptureListener
import android.util.AttributeSet
import android.view.View
import com.xing.commonlibrary.log.LogUtilsclass VisualizerView @JvmOverloads constructor(context: Context?,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) :View(context, attrs, defStyleAttr) {private val TAG = "VisualizerView"private var mBytes: ByteArray? = nullprivate var mFFTBytes: ByteArray? = nullprivate val mRect = Rect()private var mVisualizer: Visualizer? = nullprivate var mRenderers: MutableSet<Renderer> = HashSet()var left1 = 0var top1 = 0var right1 = 0var bottom1 = 0private var mCanvas: Canvas? = nullprivate var mAudioSamplingTime: Long = 0private var mFftSamplingTime: Long = 0private val mSamplingTime = 100 //數(shù)據(jù)采樣時間間隔private var isLink = falseinit {setLayerType(LAYER_TYPE_SOFTWARE, null) //禁止硬件加速init()}private fun init() {mBytes = nullmFFTBytes = null}override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {super.onLayout(changed, left, top, right, bottom)left1 = lefttop1 = topright1 = rightbottom1 = bottom}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)mCanvas = canvasmRect[0, 0, width] = heightmBytes?.let {// Render all audio renderersfor (r in mRenderers) {r.audioRender(canvas, it, mRect)}}mFFTBytes?.let {// Render all FFT renderersfor (r in mRenderers) {r.fftRender(canvas, it, mRect)}}}fun link(musicId: Int) {try {//使用前先釋放if (mVisualizer != null) {release()}if (mVisualizer == null && !isLink) {mVisualizer = Visualizer(musicId)isLink = true}LogUtils.e(TAG, "nsc =" + mVisualizer?.enabled)mVisualizer?.enabled = falsemVisualizer?.captureSize = Visualizer.getCaptureSizeRange()[1]// Pass through Visualizer data to VisualizerViewval captureListener: OnDataCaptureListener = object : OnDataCaptureListener {override fun onWaveFormDataCapture(visualizer: Visualizer, bytes: ByteArray,samplingRate: Int) {val currentTimeMillis = System.currentTimeMillis()LogUtils.i(TAG, "onWaveFormDataCapture")if (currentTimeMillis - mAudioSamplingTime >= mSamplingTime) {mBytes = bytesinvalidate()mAudioSamplingTime = currentTimeMillis}}override fun onFftDataCapture(visualizer: Visualizer, bytes: ByteArray,samplingRate: Int) {LogUtils.i(TAG, "onFftDataCapture")val currentTimeMillis = System.currentTimeMillis()if (currentTimeMillis - mFftSamplingTime >= mSamplingTime) {mFFTBytes = bytesinvalidate()mFftSamplingTime = currentTimeMillis}}}mVisualizer?.setDataCaptureListener(captureListener,Visualizer.getMaxCaptureRate() / 2,true,true)// Enabled Visualizer and disable when we're done with the streammVisualizer?.enabled = true} catch (e: RuntimeException) {}}fun setVisualizerEnable(flag: Boolean) {mVisualizer?.enabled = flag}fun release() {mVisualizer?.enabled = falsemVisualizer?.release()mVisualizer = nullisLink = false}fun addRenderer(renderer: Renderer?) {if (renderer != null) {mRenderers.add(renderer)}}fun clearRenderers() {mRenderers.clear()}
}
5. 實現(xiàn)簡單的柱狀顯示

實現(xiàn)很簡單,就是將拿到的數(shù)據(jù)通過canvas.drawLines繪制出來,

class ColumnarRenderer( private val mPaint: Paint) : Renderer() {private val mSpectrumNum = 96override fun onAudioRender(canvas: Canvas, data: ByteArray, rect: Rect) {}override fun onFftRender(canvas: Canvas, data: ByteArray, rect: Rect) {val baseX = rect.width() / mSpectrumNumval height = rect.height()for (i in 0 until mSpectrumNum) {val magnitude = (baseX * i + baseX / 2).toFloat()mFFTPoints?.let {it[i * 4] = magnitudeit[i * 4 + 1] = (height / 2).toFloat()it[i * 4 + 2] = magnitudeit[i * 4 + 3] = (height / 2 - data[i] * 4).toFloat()}}mFFTPoints?.let { canvas.drawLines(it, mPaint) }}
}

然后調(diào)用visualizerView添加到Renderer即可

 visualizerView.addRenderer(columnarRenderer);
6.實現(xiàn)能量塊跳動

代碼里面有詳細(xì)備注

package com.example.knowledgemanagement.visualizerimport android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import java.util.Random
import kotlin.math.abs
import kotlin.math.hypotclass EnergyBlockRenderer(private val mPaint: Paint) : Renderer() {companion object {private const val TAG = "EnergyBlockRenderer"private const val MAX_LEVEL = 30 //音量柱·音頻塊 - 最大個數(shù)private const val CYLINDER_NUM = 26 //音量柱 - 最大個數(shù)private const val DN_W = 470 //view寬度與單個音頻塊占比 - 正常480 需微調(diào)private const val DN_H = 300 //view高度與單個音頻塊占比private const val DN_SL = 10 //單個音頻塊寬度private const val DN_SW = 2 //單個音頻塊高度}private var mData = ByteArray(CYLINDER_NUM) //音量柱 數(shù)組private var hGap = 0private var vGap = 0private var levelStep = 0private var strokeWidth = 0fprivate var strokeLength = 0fvar mDataEn = trueinit {levelStep = 230 / MAX_LEVEL}fun onLayout(left: Int, top: Int, right: Int, bottom: Int) {val w: Float = (right - left).toFloat()val h: Float = (bottom - top).toFloat()val xr: Float = w / DN_W.toFloat()val yr: Float = h / DN_H.toFloat()strokeWidth = DN_SW * yrstrokeLength = DN_SL * xrhGap = ((w - strokeLength * CYLINDER_NUM) / (CYLINDER_NUM + 1)).toInt()vGap = (h / (MAX_LEVEL + 2)).toInt() //頻譜塊高度mPaint.strokeWidth = strokeWidth //設(shè)置頻譜塊寬度}//繪制頻譜塊和倒影private fun drawCylinder(canvas: Canvas, x: Float, value: Byte, rect: Rect) {var value = valueif (value.toInt() == 0) {value = 1} //最少有一個頻譜塊for (i in 0 until value) { //每個能量柱繪制value個能量塊val y = (rect.height() / 2 - i * vGap / 2 - vGap).toFloat() //計算y軸坐標(biāo)val y1 = (rect.height() / 2 + i * vGap / 2 + vGap).toFloat()//繪制頻譜塊mPaint.color = color //畫筆顏色canvas.drawLine(x, y, x + strokeLength, y, mPaint) //繪制頻譜塊//繪制音量柱倒影if (i <= 6 && value > 0) {mPaint.color = Color.WHITE //畫筆顏色mPaint.alpha = 100 - 100 / 6 * i //倒影顏色canvas.drawLine(x, y1, x + strokeLength, y1, mPaint) //繪制頻譜塊}}}private val color: Intprivate get() {val ranColor = intArrayOf(Color.RED, Color.YELLOW, Color.MAGENTA, Color.BLUE, Color.GREEN, Color.GRAY,Color.CYAN, Color.LTGRAY, Color.TRANSPARENT)val random = Random()val value = random.nextInt(ranColor.size - 1)return ranColor[value]}override fun onAudioRender(canvas: Canvas, data: ByteArray, rect: Rect) {}override fun onFftRender(canvas: Canvas, data: ByteArray, rect: Rect) {val model = ByteArray(data.size / 2 + 1)if (mDataEn) {model[0] = abs(data[1].toInt()).toByte()var j = 1var i = 2while (i < data.size) {model[j] = hypot(data[i].toDouble(), data[i + 1].toDouble()).toInt().toByte()i += 2j++}} else {for (i in 0 until CYLINDER_NUM) {model[i] = 0}}for (i in 0 until CYLINDER_NUM) {val a = (abs(model[CYLINDER_NUM - i].toInt()) / levelStep).toByte()val b = mData[i]if (a > b) {mData[i] = a} else {if (b > 0) {mData[i]--}}}var j = -4for (i in 0 until CYLINDER_NUM / 2 - 4) {drawCylinder(canvas, strokeWidth / 2 + hGap + i * (hGap + strokeLength), mData[i], rect)}for (i in CYLINDER_NUM downTo CYLINDER_NUM / 2 - 4) {j++drawCylinder(canvas, strokeWidth / 2 + hGap + (CYLINDER_NUM / 2 + j - 1) * (hGap + strokeLength), mData[i - 1], rect)}}}

Render代碼

package com.example.knowledgemanagement.visualizerimport android.graphics.Canvas
import android.graphics.Rectabstract class Renderer {// Have these as members, so we don't have to re-create them each timevar mPoints: FloatArray? = nullvar mFFTPoints: FloatArray? = nullvar isPlaying = true// As the display of raw/FFT audio will usually look different, subclasses// will typically only implement one of the below methods/*** Implement this method to audioRender the audio data onto the canvas** @param canvas - Canvas to draw on* @param data   - Data to audioRender* @param rect   - Rect to audioRender into*/abstract fun onAudioRender(canvas: Canvas, data: ByteArray, rect: Rect)/*** Implement this method to audioRender the FFT audio data onto the canvas** @param canvas - Canvas to draw on* @param data   - Data to audioRender* @param rect   - Rect to audioRender into*/abstract fun onFftRender(canvas: Canvas, data: ByteArray, rect: Rect)// These methods should actually be called for rendering/*** Render the audio data onto the canvas** @param canvas - Canvas to draw on* @param data   - Data to audioRender* @param rect   - Rect to audioRender into*/fun audioRender(canvas: Canvas, data: ByteArray, rect: Rect) {if (mPoints == null || mPoints!!.size < data.size * 4) {mPoints = FloatArray(data.size * 4)}onAudioRender(canvas, data, rect)}/*** Render the FFT data onto the canvas** @param canvas - Canvas to draw on* @param data   - Data to audioRender* @param rect   - Rect to audioRender into*/fun fftRender(canvas: Canvas, data: ByteArray, rect: Rect) {if (mFFTPoints == null || mFFTPoints!!.size < data.size * 4) {mFFTPoints = FloatArray(data.size * 4)}onFftRender(canvas, data, rect)}
}
7. 錯誤原因跟解決辦法

下面錯誤是因為沒有獲取音樂的SessionId傳入,傳了0導(dǎo)致的問題。

The Visualizer initCheck failed -3 error typically occurs due to missing 
permissions, invalid audio session IDs, hardware limitations, or timing issues. 
By addressing these potential causes, you should be able to resolve the issue and 
successfully initialize the Visualizer in your Android application.

想看更詳細(xì)的介紹可以看谷歌文檔:Visualizer ?|? Android Developers

代碼下載:https://download.csdn.net/download/u011324501/90038203

http://www.risenshineclean.com/news/37125.html

相關(guān)文章:

  • 住房和城鄉(xiāng)建設(shè)部網(wǎng)站買賣合同seo網(wǎng)站推廣經(jīng)理招聘
  • 做外貿(mào)翻譯用哪個網(wǎng)站網(wǎng)站建設(shè)公司業(yè)務(wù)
  • html5軟件下載手機版網(wǎng)頁關(guān)鍵詞排名優(yōu)化
  • 網(wǎng)站界面需求網(wǎng)絡(luò)推廣課程培訓(xùn)
  • windows搭建網(wǎng)站開發(fā)推廣軟件
  • 旬陽做網(wǎng)站seo計費系統(tǒng)源碼
  • 網(wǎng)站建設(shè)創(chuàng)新能力痛點湖南百度推廣代理商
  • wordpress分類鏈接網(wǎng)站如何進行優(yōu)化
  • 珠海網(wǎng)站搜索引擎優(yōu)化青島seo服務(wù)
  • o2o網(wǎng)站做推廣公司小視頻關(guān)鍵詞匯總
  • 漫畫網(wǎng)站css模板登錄百度app
  • 宜春代做網(wǎng)站自己做一個網(wǎng)站要多少錢
  • 文昌建設(shè)局網(wǎng)站今日nba數(shù)據(jù)帝
  • 南京做網(wǎng)站建設(shè)搭建的公司app推廣方案策劃
  • 千博企業(yè)網(wǎng)站系統(tǒng)論壇推廣案例
  • 手表網(wǎng)站建設(shè)策劃書深圳門戶網(wǎng)站
  • 長春火車站在哪個區(qū)網(wǎng)站收錄查詢代碼
  • 網(wǎng)站建設(shè)需要什么專業(yè)如何推廣平臺
  • 用手機建網(wǎng)站的步驟線上it培訓(xùn)機構(gòu)
  • 阿里云虛擬主機可以做幾個網(wǎng)站嗎長沙網(wǎng)絡(luò)推廣軟件
  • 東莞 網(wǎng)站建設(shè)seo查詢平臺
  • seo做的好的網(wǎng)站有哪些哪個模板建站好
  • 網(wǎng)站建設(shè)需要哪些資料網(wǎng)站建設(shè)與網(wǎng)站設(shè)計
  • 寵物社區(qū)網(wǎng)站開發(fā)設(shè)計文檔網(wǎng)絡(luò)整合營銷方案
  • 那里有個人做網(wǎng)站的網(wǎng)址推薦
  • 第一次開票網(wǎng)站建設(shè)怎么開公司如何建立網(wǎng)站
  • 網(wǎng)站開發(fā)通用流程圖廈門seo排名公司
  • 中文網(wǎng)站建設(shè)小組企業(yè)推廣策劃書
  • 大連商城網(wǎng)站制作公司b站免費版入口
  • 做電子章網(wǎng)站可以下載新聞視頻的網(wǎng)站