Back to project page renderScriptFFT.
The source code is released under:
Copyright (c) 2013 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided...
If you think the Android project renderScriptFFT listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.android.rs; /*from w ww.j a v a2 s. c o m*/ import java.io.File; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.res.Resources; import android.os.Environment; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.Int2; import android.renderscript.RenderScript; import android.renderscript.Type; import com.android.rs.mel.DCT; import com.android.rs.mel.HammingFilter; import com.android.rs.mel.MelFilterbank; import com.android.rs.utils.ArrayConversion; import com.example.renderscriptfft.R; import com.musicg.wave.Wave; public class Mel_Test_MicroBench extends Thread { private boolean msgHandled; public int result; protected Context mCtx; private Resources mRes; public Mel_Test_MicroBench(Resources mRes, Context mCtx) { super(); this.mCtx = mCtx; this.mRes = mRes; msgHandled = false; setup(); } private int sampleFreq, frameSize, numFrames, numFilters, xWidth, nCeps; private Int2 fftRange; private RenderScript mRS; private ScriptC_fft fftScript; private ScriptC_filterMultiplication fMult; private ScriptC_powerCalc powerCalc; private ScriptC_parallelSum parSum; private ScriptC_logDataSet logDataSet; private ScriptC_melFilterResps melResp; private ScriptC_rearrangeFilterResp rearrangeFilterResp; private ScriptC_computeDCT computeDCT; private Allocation mAudioAllocation, mHamFilterData, mMelFilterData, mDCTData, mFFTAllocation, mSamplesInFreq, mPowerInFreq, mSumPowerInFreq, mMelFilterResps, mRearrangeResp, mFFTResp, mDCTY, mMelCeps; private float[] testData; public void waitForMessage() { while (!msgHandled) { yield(); } } private void setup() { mRS = RenderScript.create(mCtx); frameSize = 128; sampleFreq = 8000; numFilters = 32; nCeps = 12; // Open test input file File file = new File(Environment.getExternalStorageDirectory(), "Download/16b_8k.wav"); Wave w = new Wave(file.toString()); //Follow Matlab example wave emphasis float[] emphDat = emphData(ArrayConversion.doublesToFloats(w .getNormalizedAmplitudes()), 0.97f); int shiftLength = 10000 - 1; //int shiftLength = 0; float[] shiftData = new float[emphDat.length - shiftLength]; System.arraycopy(emphDat, shiftLength, shiftData, 0, shiftData.length); testData = ArrayConversion.createRealImag(shiftData, frameSize); //double[] oneframe = new double[] {-0.00148040771484376,-0.00926818847656249,-0.0174041748046875,-0.0262582397460938,-0.0343191528320312,-0.0430511474609375,-0.0381552124023438,-0.0357562255859375,-0.0387728881835938,-0.0271377563476563,-0.0243048095703125,-0.0258804321289063,-0.0200067138671875,-0.0247088623046875,-0.0159265136718750,-0.0137896728515625,-0.0165225219726562,-0.00361297607421876,0.000141906738281239,0.00446533203124999,0.0135824584960937,0.0182949829101562,0.0278622436523437,0.0381231689453125,0.0441467285156250,0.0515347290039063,0.0486660766601563,0.0470684814453125,0.0459906005859375,0.0348916625976563,0.0225064086914062,0.0145141601562500,0.00199493408203125,-0.0106933593750000,-0.0197601318359375,-0.0255126953125000,-0.0319638061523437,-0.0380007934570313,-0.0387234497070312,-0.0368975830078125,-0.0325082397460938,-0.0270681762695313,-0.0257693481445312,-0.0229129028320313,-0.0266326904296875,-0.0219924926757813,-0.0197250366210938,-0.0229885864257813,-0.0161129760742187,-0.00932006835937502,-0.00377868652343752,0.00708953857421873,0.0139178466796875,0.0219769287109375,0.0315420532226562,0.0393862915039063,0.0454501342773438,0.0528784179687500,0.0504467773437500,0.0478942871093750,0.0430541992187500,0.0350985717773438,0.0254959106445312,0.0131369018554688,-0.00180755615234374,-0.0104006958007812,-0.0173822021484375,-0.0247103881835938,-0.0301925659179687,-0.0334927368164062,-0.0405227661132813,-0.0362557983398438,-0.0326461791992188,-0.0327093505859375,-0.0270077514648438,-0.0244635009765625,-0.0259707641601563,-0.0203625488281250,-0.0192959594726563,-0.0182131958007813,-0.0131784057617187,-0.00718719482421876,-0.00125335693359377,0.00791168212890625,0.0152725219726562,0.0200955200195312,0.0263571166992188,0.0360192871093750,0.0398101806640625,0.0459381103515625,0.0477569580078125,0.0445532226562500,0.0398989868164063,0.0396447753906250,0.0279061889648438,0.0203005981445313,0.00735046386718752,-0.00490203857421875,-0.0116632080078125,-0.0195932006835937,-0.0280804443359375,-0.0320996093750000,-0.0396884155273437,-0.0395071411132813,-0.0361996459960938,-0.0328472900390625,-0.0317111206054688,-0.0307559204101563,-0.0233056640625000,-0.0232052612304688,-0.0211001586914062,-0.0147335815429687,-0.0165838623046875,-0.0112481689453125,-0.00208007812500000,-0.000871582031250012,0.0108984375000000,0.0149301147460937,0.0195257568359375,0.0315655517578125,0.0387265014648437,0.0435681152343750,0.0495248413085938,0.0483261108398438,0.0447274780273438,0.0421994018554688,0.0389169311523438,0.0243627929687500}; //testData = ArrayConversion.createRealImag(ArrayConversion.doublesToFloats(oneframe), frameSize); //1MB //double[] runTest = new double[262144]; //5MB 1310720 //double[] runTest = new double[1310720]; //10MB 2621440 //double[] runTest = new double[2621440]; //15MB 3932160 //double[] runTest = new double[3932160]; //testData = ArrayConversion.createRealImag(ArrayConversion.doublesToFloats(runTest), frameSize); //Convert wave data to float2 array and copy over to device. //Note: In the future we probably want to create a separate method to //do this in real time for mic input numFrames = (testData.length / 2) / frameSize; Type.Builder typeBuilder = new Type.Builder(mRS, Element.F32_2(mRS)); typeBuilder.setX(frameSize).setY(numFrames); mAudioAllocation = Allocation.createTyped(mRS,typeBuilder.create()); //Create hamming window that will be used HammingFilter hf = new HammingFilter(frameSize); float[] hamData = ArrayConversion.doublesToFloats(hf.getHamFilter()); mHamFilterData = Allocation.createSized(mRS, Element.F32(mRS), hamData.length); mHamFilterData.copyFrom(hamData); //Create Mel Filter bank MelFilterbank mf = new MelFilterbank(numFilters, frameSize, sampleFreq, 0, .5); float[] melFilterBank = mf.getFlattenedFilterBank(); fftRange = mf.getFFTRange(); //Calculate DCT DCT dtc = new DCT(numFilters); mDCTData = Allocation.createSized(mRS, Element.F32_2(mRS), numFilters); mDCTData.copyFrom(ArrayConversion.doublesToFloats(dtc.getCoeffs())); //Set up scripts //Hamming Filter fMult = new ScriptC_filterMultiplication(mRS, mRes, R.raw.filtermultiplication); fMult.set_gFilter(mHamFilterData); //FFT fftScript = new ScriptC_fft(mRS, mRes, R.raw.fft); mFFTAllocation = Allocation.createTyped(mRS,typeBuilder.create()); //Samples in Freq xWidth = fftRange.y - fftRange.x + 1; //y is upper limit. x is lower typeBuilder.setX(xWidth).setY(numFrames); mSamplesInFreq = Allocation.createTyped(mRS,typeBuilder.create()); //Power Scripts powerCalc = new ScriptC_powerCalc(mRS, mRes, R.raw.powercalc); typeBuilder = new Type.Builder(mRS, Element.F32(mRS)); typeBuilder.setX(xWidth).setY(numFrames); mPowerInFreq = Allocation.createTyped(mRS,typeBuilder.create()); parSum = new ScriptC_parallelSum(mRS, mRes, R.raw.parallelsum); typeBuilder.setX(1).setY(numFrames); mSumPowerInFreq = Allocation.createTyped(mRS,typeBuilder.create()); logDataSet = new ScriptC_logDataSet(mRS, mRes, R.raw.logdataset); //Mel Filter Responses typeBuilder.setX(mf.getNumCols()).setY(mf.getNumRows()); mMelFilterData = Allocation.createTyped(mRS, typeBuilder.create()); mMelFilterData.copy2DRangeFrom(0, 0, mf.getNumCols(), mf.getNumRows(), melFilterBank); melResp = new ScriptC_melFilterResps(mRS, mRes, R.raw.melfilterresps); melResp.set_gMelFilterBank(mMelFilterData); melResp.set_gInputFreq(mSamplesInFreq); melResp.set_numElements(mf.getNumCols()); melResp.set_numFilters(mf.getNumRows()); typeBuilder = new Type.Builder(mRS, Element.F32_2(mRS)); typeBuilder.setX(numFilters).setY(numFrames); mMelFilterResps = Allocation.createTyped(mRS, typeBuilder.create()); rearrangeFilterResp = new ScriptC_rearrangeFilterResp(mRS, mRes, R.raw.rearrangefilterresp); rearrangeFilterResp.invoke_setup(numFilters); mRearrangeResp = Allocation.createTyped(mRS, typeBuilder.create()); mFFTResp = Allocation.createTyped(mRS, typeBuilder.create()); typeBuilder = new Type.Builder(mRS, Element.F32(mRS)); typeBuilder.setX(numFilters).setY(numFrames); mDCTY = Allocation.createTyped(mRS, typeBuilder.create()); computeDCT = new ScriptC_computeDCT(mRS, mRes, R.raw.computedct); computeDCT.invoke_setup(numFilters, mDCTData); typeBuilder.setX(nCeps+1).setY(numFrames); mMelCeps = Allocation.createTyped(mRS, typeBuilder.create()); } private List<Long> time = new ArrayList<Long>(); public List<Long> getTime(){ return time; } public void run() { time.clear(); long startTime, stopTime; //Copy current audio data mAudioAllocation.copy2DRangeFrom(0, 0, frameSize, numFrames, testData); //Smooth samples for all input windows (Apply Hamming window) startTime = System.currentTimeMillis(); fMult.forEach_root(mAudioAllocation, mAudioAllocation); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Perform fft startTime = System.currentTimeMillis(); fftScript.invoke_runRestricted(fftScript, mAudioAllocation, mFFTAllocation); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Depending on the iteration, the final data in the FFT can be either the in or out array Allocation fftOut; if (fftScript.get_finalFFT() == 0) fftOut = mFFTAllocation; else fftOut = mAudioAllocation; //Get valid range of fft (equivalent of samples_in_freq(fftA:fftB)) in original Matlab code startTime = System.currentTimeMillis(); mSamplesInFreq.copy2DRangeFrom(0, 0, xWidth, numFrames, fftOut, fftRange.x, 0); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Find the power of the samples startTime = System.currentTimeMillis(); powerCalc.forEach_root(mSamplesInFreq, mPowerInFreq); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Sum the power up (this can be improved with a better parallel reduction) startTime = System.currentTimeMillis(); parSum.invoke_runRestricted(parSum, mPowerInFreq, mSumPowerInFreq); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); startTime = System.currentTimeMillis(); logDataSet.forEach_root(mSumPowerInFreq,mSumPowerInFreq); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Compute the Mel Filter Responses startTime = System.currentTimeMillis(); melResp.forEach_root(mMelFilterResps, mMelFilterResps); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); startTime = System.currentTimeMillis(); rearrangeFilterResp.forEach_root(mMelFilterResps, mRearrangeResp); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Perform fft on rearranged responses startTime = System.currentTimeMillis(); fftScript.invoke_runRestricted(fftScript, mRearrangeResp, mFFTResp); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Depending on the iteration, the final data in the FFT can be either the in or out array if (fftScript.get_finalFFT() == 0) fftOut = mFFTResp; else fftOut = mRearrangeResp; //Compute Discrete Cosine transform startTime = System.currentTimeMillis(); computeDCT.forEach_root(fftOut, mDCTY); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); //Compute Mel Ceps startTime = System.currentTimeMillis(); mMelCeps.copy2DRangeFrom(0, 0, 1, numFrames, mSumPowerInFreq, 0, 0); mMelCeps.copy2DRangeFrom(1, 0, nCeps, numFrames, mDCTY, 1, 0); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); startTime = System.currentTimeMillis(); float[] debug = new float[(nCeps+1)*numFrames]; mMelCeps.copyTo(debug); mRS.finish(); stopTime = System.currentTimeMillis(); time.add(stopTime - startTime); } //This is the pre-emphasis filter that was used for the input data in matlab private float[] emphData(float[] data, float emph){ float[] tmpData = new float[data.length]; tmpData[0] = data[0]; for (int i = 1; i < data.length; ++i){ tmpData[i] = data[i] - emph * data[i-1]; } return tmpData; } }