前一段实习,本来打算做c++,到了公司发现没啥项目,于是乎转行做了android,写的第一个程序竟然要我处理信号,咱可是一心搞计算机的,没接触过信号的东西,什么都没接触过,于是乎, 找各种朋友,各种熟人,现在想想,专注语言是不对的,语言就是一工具,关键还是业务,算法。好了,废话不多说,上程序,注释都很详细,应该能看懂。

分析声音,其实很简单,就是运用傅里叶变换,将声音信号由时域转化到频域(程序用的是快速傅里叶变换,比较简单),为啥要这样,好处多多,不细讲,公司里的用处是为了检测手机发出声音的信号所在的频率集中范围。

第一个类,复数的计算,用到加减乘,很简单。

  1. package com.mobao360.sunshine;
  2. //复数的加减乘运算
  3. public class Complex {
  4. public double real;
  5. public double image;
  6. //三个构造函数
  7. public Complex() {
  8. // TODO Auto-generated constructor stub
  9. this.real = 0;
  10. this.image = 0;
  11. }
  12. public Complex(double real, double image){
  13. this.real = real;
  14. this.image = image;
  15. }
  16. public Complex(int real, int image) {
  17. Integer integer = real;
  18. this.real = integer.floatValue();
  19. integer = image;
  20. this.image = integer.floatValue();
  21. }
  22. public Complex(double real) {
  23. this.real = real;
  24. this.image = 0;
  25. }
  26. //乘法
  27. public Complex cc(Complex complex) {
  28. Complex tmpComplex = new Complex();
  29. tmpComplex.real = this.real * complex.real - this.image * complex.image;
  30. tmpComplex.image = this.real * complex.image + this.image * complex.real;
  31. return tmpComplex;
  32. }
  33. //加法
  34. public Complex sum(Complex complex) {
  35. Complex tmpComplex = new Complex();
  36. tmpComplex.real = this.real + complex.real;
  37. tmpComplex.image = this.image + complex.image;
  38. return tmpComplex;
  39. }
  40. //减法
  41. public Complex cut(Complex complex) {
  42. Complex tmpComplex = new Complex();
  43. tmpComplex.real = this.real - complex.real;
  44. tmpComplex.image = this.image - complex.image;
  45. return tmpComplex;
  46. }
  47. //获得一个复数的值
  48. public int getIntValue(){
  49. int ret = 0;
  50. ret = (int) Math.round(Math.sqrt(this.real*this.real - this.image*this.image));
  51. return ret;
  52. }
  53. }

这个类是有三个功能,第一,采集数据;第二,进行快速傅里叶计算;第三,绘图。

采集数据用AudioRecord类,网上讲解这个类的蛮多的,搞清楚构造类的各个参数就可以。

绘图用的是SurfaceView Paint Canvas三个类,本人也是参考网络达人的代码

  1. package com.mobao360.sunshine;
  2. import java.util.ArrayList;
  3. import java.lang.Short;
  4. import android.content.Context;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.DashPathEffect;
  8. import android.graphics.Paint;
  9. import android.graphics.Path;
  10. import android.graphics.PathEffect;
  11. import android.graphics.Rect;
  12. import android.media.AudioRecord;
  13. import android.util.Log;
  14. import android.view.SurfaceView;
  15. public class AudioProcess {
  16. public static final float pi= (float) 3.1415926;
  17. //应该把处理前后处理后的普线都显示出来
  18. private ArrayList<short[]> inBuf = new ArrayList<short[]>();//原始录入数据
  19. private ArrayList<int[]> outBuf = new ArrayList<int[]>();//处理后的数据
  20. private boolean isRecording = false;
  21. Context mContext;
  22. private int shift = 30;
  23. public int frequence = 0;
  24. private int length = 256;
  25. //y轴缩小的比例
  26. public int rateY = 21;
  27. //y轴基线
  28. public int baseLine = 0;
  29. //初始化画图的一些参数
  30. public void initDraw(int rateY, int baseLine,Context mContext, int frequence){
  31. this.mContext = mContext;
  32. this.rateY = rateY;
  33. this.baseLine = baseLine;
  34. this.frequence = frequence;
  35. }
  36. //启动程序
  37. public void start(AudioRecord audioRecord, int minBufferSize, SurfaceView sfvSurfaceView) {
  38. isRecording = true;
  39. new RecordThread(audioRecord, minBufferSize).start();
  40. new DrawThread(sfvSurfaceView).start();
  41. }
  42. //停止程序
  43. public void stop(SurfaceView sfvSurfaceView){
  44. isRecording = false;
  45. inBuf.clear();
  46. }
  47. //录音线程
  48. class RecordThread extends Thread{
  49. private AudioRecord audioRecord;
  50. private int minBufferSize;
  51. public RecordThread(AudioRecord audioRecord,int minBufferSize){
  52. this.audioRecord = audioRecord;
  53. this.minBufferSize = minBufferSize;
  54. }
  55. public void run(){
  56. try{
  57. short[] buffer = new short[minBufferSize];
  58. audioRecord.startRecording();
  59. while(isRecording){
  60. int res = audioRecord.read(buffer, 0, minBufferSize);
  61. synchronized (inBuf){
  62. inBuf.add(buffer);
  63. }
  64. //保证长度为2的幂次数
  65. length=up2int(res);
  66. short[]tmpBuf = new short[length];
  67. System.arraycopy(buffer, 0, tmpBuf, 0, length);
  68. Complex[]complexs = new Complex[length];
  69. int[]outInt = new int[length];
  70. for(int i=0;i < length; i++){
  71. Short short1 = tmpBuf[i];
  72. complexs[i] = new Complex(short1.doubleValue());
  73. }
  74. fft(complexs,length);
  75. for (int i = 0; i < length; i++) {
  76. outInt[i] = complexs[i].getIntValue();
  77. }
  78. synchronized (outBuf) {
  79. outBuf.add(outInt);
  80. }
  81. }
  82. audioRecord.stop();
  83. }catch (Exception e) {
  84. // TODO: handle exception
  85. Log.i("Rec E",e.toString());
  86. }
  87. }
  88. }
  89. //绘图线程
  90. class DrawThread extends Thread{
  91. //画板
  92. private SurfaceView sfvSurfaceView;
  93. //当前画图所在屏幕x轴的坐标
  94. //画笔
  95. private Paint mPaint;
  96. private Paint tPaint;
  97. private Paint dashPaint;
  98. public DrawThread(SurfaceView sfvSurfaceView) {
  99. this.sfvSurfaceView = sfvSurfaceView;
  100. //设置画笔属性
  101. mPaint = new Paint();
  102. mPaint.setColor(Color.BLUE);
  103. mPaint.setStrokeWidth(2);
  104. mPaint.setAntiAlias(true);
  105. tPaint = new Paint();
  106. tPaint.setColor(Color.YELLOW);
  107. tPaint.setStrokeWidth(1);
  108. tPaint.setAntiAlias(true);
  109. //画虚线
  110. dashPaint = new Paint();
  111. dashPaint.setStyle(Paint.Style.STROKE);
  112. dashPaint.setColor(Color.GRAY);
  113. Path path = new Path();
  114. path.moveTo(0, 10);
  115. path.lineTo(480,10);
  116. PathEffect effects = new DashPathEffect(new float[]{5,5,5,5},1);
  117. dashPaint.setPathEffect(effects);
  118. }
  119. @SuppressWarnings("unchecked")
  120. public void run() {
  121. while (isRecording) {
  122. ArrayList<int[]>buf = new ArrayList<int[]>();
  123. synchronized (outBuf) {
  124. if (outBuf.size() == 0) {
  125. continue;
  126. }
  127. buf = (ArrayList<int[]>)outBuf.clone();
  128. outBuf.clear();
  129. }
  130. //根据ArrayList中的short数组开始绘图
  131. for(int i = 0; i < buf.size(); i++){
  132. int[]tmpBuf = buf.get(i);
  133. SimpleDraw(tmpBuf, rateY, baseLine);
  134. }
  135. }
  136. }
  137. /**
  138. * 绘制指定区域
  139. *
  140. * @param start
  141. *            X 轴开始的位置(全屏)
  142. * @param buffer
  143. *             缓冲区
  144. * @param rate
  145. *            Y 轴数据缩小的比例
  146. * @param baseLine
  147. *            Y 轴基线
  148. */
  149. private void SimpleDraw(int[] buffer, int rate, int baseLine){
  150. Canvas canvas = sfvSurfaceView.getHolder().lockCanvas(
  151. new Rect(0, 0, buffer.length,sfvSurfaceView.getHeight()));
  152. canvas.drawColor(Color.BLACK);
  153. canvas.drawText("幅度值", 0, 3, 2, 15, tPaint);
  154. canvas.drawText("原点(0,0)", 0, 7, 5, baseLine + 15, tPaint);
  155. canvas.drawText("频率(HZ)", 0, 6, sfvSurfaceView.getWidth() - 50, baseLine + 30, tPaint);
  156. canvas.drawLine(shift, 20, shift, baseLine, tPaint);
  157. canvas.drawLine(shift, baseLine, sfvSurfaceView.getWidth(), baseLine, tPaint);
  158. canvas.save();
  159. canvas.rotate(30, shift, 20);
  160. canvas.drawLine(shift, 20, shift, 30, tPaint);
  161. canvas.rotate(-60, shift, 20);
  162. canvas.drawLine(shift, 20, shift, 30, tPaint);
  163. canvas.rotate(30, shift, 20);
  164. canvas.rotate(30, sfvSurfaceView.getWidth()-1, baseLine);
  165. canvas.drawLine(sfvSurfaceView.getWidth() - 1, baseLine, sfvSurfaceView.getWidth() - 11, baseLine, tPaint);
  166. canvas.rotate(-60, sfvSurfaceView.getWidth()-1, baseLine);
  167. canvas.drawLine(sfvSurfaceView.getWidth() - 1, baseLine, sfvSurfaceView.getWidth() - 11, baseLine, tPaint);
  168. canvas.restore();
  169. //tPaint.setStyle(Style.STROKE);
  170. for(int index = 64; index <= 512; index = index + 64){
  171. canvas.drawLine(shift + index, baseLine, shift + index, 40, dashPaint);
  172. String str = String.valueOf(frequence / 1024 * index);
  173. canvas.drawText( str, 0, str.length(), shift + index - 15, baseLine + 15, tPaint);
  174. }
  175. int y;
  176. for(int i = 0; i < buffer.length; i = i + 1){
  177. y = baseLine - buffer[i] / rateY ;
  178. canvas.drawLine(2*i + shift, baseLine, 2*i +shift, y, mPaint);
  179. }
  180. sfvSurfaceView.getHolder().unlockCanvasAndPost(canvas);
  181. }
  182. }
  183. /**
  184. * 向上取最接近iint的2的幂次数.比如iint=320时,返回256
  185. * @param iint
  186. * @return
  187. */
  188. private int up2int(int iint) {
  189. int ret = 1;
  190. while (ret<=iint) {
  191. ret = ret << 1;
  192. }
  193. return ret>>1;
  194. }
  195. //快速傅里叶变换
  196. public void fft(Complex[] xin,int N)
  197. {
  198. int f,m,N2,nm,i,k,j,L;//L:运算级数
  199. float p;
  200. int e2,le,B,ip;
  201. Complex w = new Complex();
  202. Complex t = new Complex();
  203. N2 = N / 2;//每一级中蝶形的个数,同时也代表m位二进制数最高位的十进制权值
  204. f = N;//f是为了求流程的级数而设立的
  205. for(m = 1; (f = f / 2) != 1; m++);                             //得到流程图的共几级
  206. nm = N - 2;
  207. j = N2;
  208. /******倒序运算——雷德算法******/
  209. for(i = 1; i <= nm; i++)
  210. {
  211. if(i < j)//防止重复交换
  212. {
  213. t = xin[j];
  214. xin[j] = xin[i];
  215. xin[i] = t;
  216. }
  217. k = N2;
  218. while(j >= k)
  219. {
  220. j = j - k;
  221. k = k / 2;
  222. }
  223. j = j + k;
  224. }
  225. /******蝶形图计算部分******/
  226. for(L=1; L<=m; L++)                                    //从第1级到第m级
  227. {
  228. e2 = (int) Math.pow(2, L);
  229. //e2=(int)2.pow(L);
  230. le=e2+1;
  231. B=e2/2;
  232. for(j=0;j<B;j++)                                    //j从0到2^(L-1)-1
  233. {
  234. p=2*pi/e2;
  235. w.real = Math.cos(p * j);
  236. //w.real=Math.cos((double)p*j);                                   //系数W
  237. w.image = Math.sin(p*j) * -1;
  238. //w.imag = -sin(p*j);
  239. for(i=j;i<N;i=i+e2)                                //计算具有相同系数的数据
  240. {
  241. ip=i+B;                                           //对应蝶形的数据间隔为2^(L-1)
  242. t=xin[ip].cc(w);
  243. xin[ip] = xin[i].cut(t);
  244. xin[i] = xin[i].sum(t);
  245. }
  246. }
  247. }
  248. }
  249. }

主程序

  1. package com.mobao360.sunshine;
  2. import java.util.ArrayList;
  3. import android.app.Activity;
  4. import android.app.AlertDialog;
  5. import android.content.Context;
  6. import android.content.DialogInterface;
  7. import android.os.Bundle;
  8. import android.util.Log;
  9. import android.view.SurfaceView;
  10. import android.view.View;
  11. import android.widget.AdapterView;
  12. import android.widget.ArrayAdapter;
  13. import android.widget.Button;
  14. import android.widget.Spinner;
  15. import android.widget.TextView;
  16. import android.widget.Toast;
  17. import android.widget.ZoomControls;
  18. import android.media.AudioFormat;
  19. import android.media.AudioRecord;
  20. import android.media.MediaRecorder;
  21. public class AudioMaker extends Activity {
  22. /** Called when the activity is first created. */
  23. static  int frequency = 8000;//分辨率
  24. static final int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
  25. static final int audioEncodeing = AudioFormat.ENCODING_PCM_16BIT;
  26. static final int yMax = 50;//Y轴缩小比例最大值
  27. static final int yMin = 1;//Y轴缩小比例最小值
  28. int minBufferSize;//采集数据需要的缓冲区大小
  29. AudioRecord audioRecord;//录音
  30. AudioProcess audioProcess = new AudioProcess();//处理
  31. Button btnStart,btnExit;  //开始停止按钮
  32. SurfaceView sfv;  //绘图所用
  33. ZoomControls zctlX,zctlY;//频谱图缩放
  34. Spinner spinner;//下拉菜单
  35. ArrayList<String> list=new ArrayList<String>();
  36. ArrayAdapter<String>adapter;//下拉菜单适配器
  37. TextView tView;
  38. @Override
  39. public void onCreate(Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setContentView(R.layout.main);
  42. initControl();
  43. }
  44. @Override
  45. protected void onDestroy(){
  46. super.onDestroy();
  47. android.os.Process.killProcess(android.os.Process.myPid());
  48. }
  49. //初始化控件信息
  50. private void initControl() {
  51. //获取采样率
  52. tView = (TextView)this.findViewById(R.id.tvSpinner);
  53. spinner = (Spinner)this.findViewById(R.id.spinnerFre);
  54. String []ls =getResources().getStringArray(R.array.action);
  55. for(int i=0;i<ls.length;i++){
  56. list.add(ls[i]);
  57. }
  58. adapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,list);
  59. adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
  60. spinner.setAdapter(adapter);
  61. spinner.setPrompt("请选择采样率");
  62. spinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener(){
  63. @SuppressWarnings("unchecked")
  64. public void onItemSelected(AdapterView arg0,View agr1,int arg2,long arg3){
  65. frequency = Integer.parseInt(adapter.getItem(arg2));
  66. tView.setText("您选择的是:"+adapter.getItem(arg2)+"HZ");
  67. Log.i("sunshine",String.valueOf(minBufferSize));
  68. arg0.setVisibility(View.VISIBLE);
  69. }
  70. @SuppressWarnings("unchecked")
  71. public void onNothingSelected(AdapterView arg0){
  72. arg0.setVisibility(View.VISIBLE);
  73. }
  74. });
  75. Context mContext = getApplicationContext();
  76. //按键
  77. btnStart = (Button)this.findViewById(R.id.btnStart);
  78. btnExit = (Button)this.findViewById(R.id.btnExit);
  79. //按键事件处理
  80. btnStart.setOnClickListener(new ClickEvent());
  81. btnExit.setOnClickListener(new ClickEvent());
  82. //画笔和画板
  83. sfv = (SurfaceView)this.findViewById(R.id.SurfaceView01);
  84. //初始化显示
  85. audioProcess.initDraw(yMax/2, sfv.getHeight(),mContext,frequency);
  86. //画板缩放
  87. zctlY = (ZoomControls)this.findViewById(R.id.zctlY);
  88. zctlY.setOnZoomInClickListener(new View.OnClickListener() {
  89. @Override
  90. public void onClick(View v) {
  91. if(audioProcess.rateY - 5>yMin){
  92. audioProcess.rateY = audioProcess.rateY - 5;
  93. setTitle("Y轴缩小"+String.valueOf(audioProcess.rateY)+"倍");
  94. }else{
  95. audioProcess.rateY = 1;
  96. setTitle("原始尺寸");
  97. }
  98. }
  99. });
  100. zctlY.setOnZoomOutClickListener(new View.OnClickListener() {
  101. @Override
  102. public void onClick(View v) {
  103. if(audioProcess.rateY<yMax){
  104. audioProcess.rateY = audioProcess.rateY + 5;
  105. setTitle("Y轴缩小"+String.valueOf(audioProcess.rateY)+"倍");
  106. }else {
  107. setTitle("Y轴已经不能再缩小");
  108. }
  109. }
  110. });
  111. }
  112. /**
  113. * 按键事件处理
  114. */
  115. class ClickEvent implements View.OnClickListener{
  116. @Override
  117. public void onClick(View v){
  118. Button button = (Button)v;
  119. if(button == btnStart){
  120. if(button.getText().toString().equals("Start")){
  121. try {
  122. //录音
  123. minBufferSize = AudioRecord.getMinBufferSize(frequency,
  124. channelConfiguration,
  125. audioEncodeing);
  126. //minBufferSize = 2 * minBufferSize;
  127. audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,
  128. channelConfiguration,
  129. audioEncodeing,
  130. minBufferSize);
  131. audioProcess.baseLine = sfv.getHeight()-100;
  132. audioProcess.frequence = frequency;
  133. audioProcess.start(audioRecord, minBufferSize, sfv);
  134. Toast.makeText(AudioMaker.this,
  135. "当前设备支持您所选择的采样率:"+String.valueOf(frequency),
  136. Toast.LENGTH_SHORT).show();
  137. btnStart.setText(R.string.btn_exit);
  138. spinner.setEnabled(false);
  139. } catch (Exception e) {
  140. // TODO: handle exception
  141. Toast.makeText(AudioMaker.this,
  142. "当前设备不支持你所选择的采样率"+String.valueOf(frequency)+",请重新选择",
  143. Toast.LENGTH_SHORT).show();
  144. }
  145. }else if (button.getText().equals("Stop")) {
  146. spinner.setEnabled(true);
  147. btnStart.setText(R.string.btn_start);
  148. audioProcess.stop(sfv);
  149. }
  150. }
  151. else {
  152. new AlertDialog.Builder(AudioMaker.this)
  153. .setTitle("提示")
  154. .setMessage("确定退出?")
  155. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  156. public void onClick(DialogInterface dialog, int whichButton) {
  157. setResult(RESULT_OK);//确定按钮事件
  158. AudioMaker.this.finish();
  159. finish();
  160. }
  161. })
  162. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  163. public void onClick(DialogInterface dialog, int whichButton) {
  164. //取消按钮事件
  165. }
  166. })
  167. .show();
  168. }
  169. }
  170. }
  171. }

程序源码下载地址:http://download.csdn.net/detail/sunshine_okey/3790484

详细的看代码吧,有什么写的详细的可以留言

第一次写技术文章,写的不好,大家不要怪罪,将就着看把

基于android的实时音频频谱仪的更多相关文章

  1. 【毕业设计】基于Android的家校互动平台开发(内含完整代码和所有文档)——爱吖校推(你关注的,我们才推)

    ☆ 写在前面 之前答应大家的毕业答辩之后把所有文档贡献出来,现在答辩已过,LZ信守承诺,把所有文档开源到了GitHub(这个地址包含所有的代码和文档以及PPT,外层为简单的代码).还望喜欢的朋友们,不 ...

  2. 基于android的天气预报的设计与实现

    目录 应用开发技术及开发平台介绍 应用需求分析 应用功能设计及其描述 应用UI展示 ①开发技术: 本系统是采用面向对象的软件开发方法,基于Android studio开发平台,以Android作为本系 ...

  3. 基于Android的在线播放器系统的设计与实现

    文章结构: 1 引言 1.1系统的研究背景 现在的时代是互联网的时代,互联网高速发展的同时,无线网络也接入了互联网.社会的各个领域都已经被无线网络渗透.小的比如手机,电脑,电视.大的比如灯光系统,智能 ...

  4. 【源代码】基于Android和蓝牙的单片机温度採集系统

    如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 STC89C52单片机通过HC-06蓝牙模块与Android手机通信实例- 基于And ...

  5. 基于 Android 的 3D 视频示例代码

    笔者:Mark Liu 下载样本代码 简单介绍 在Android 中,创建一个可以播放视频剪辑的应用很easy:创建一个採用 3D 图形平面的游戏应用也很easy.可是,创建一个可以在 3D 图形对象 ...

  6. Android开发自学笔记(基于Android Studio1.3.1)—1.环境搭建(转)

    一.引言    本套学习笔记的开发环境是Windows 10 专业版和Android Studio 的最新版1.3.1. Android Studio 是一个Android开发环境,基于Intelli ...

  7. 基于 Android 的 3D 视频样本代码

    作者:Mark Liu 下载样本代码 简单介绍 在Android 中,创建一个可以播放视频剪辑的应用很easy:创建一个採用 3D 图形平面的游戏应用也很easy.可是,创建一个可以在 3D 图形对象 ...

  8. 开发一个基于 Android系统车载智能APP

    很久之前就想做一个车载相关的app.需要实现如下功能: (1)每0.2秒更新一次当前车辆的最新速度值. (2)可控制性记录行驶里程. (3)不连接网络情况下获取当前车辆位置.如(北京市X区X路X号) ...

  9. matlab中的实时音频

    音频系统工具箱™针对实时音频处理进行了优化.audioDeviceReader, audioDeviceWriter, audioPlayerRecorder, dsp.AudioFileReader ...

随机推荐

  1. ActionBar开启Overlay Mode(覆盖模式)

    以下内容参考自Android官网http://developer.android.com/training/basics/actionbar/overlaying.html#EnableOverlay ...

  2. BZOJ 3391: [Usaco2004 Dec]Tree Cutting网络破坏( dfs )

    因为是棵树 , 所以直接 dfs 就好了... ---------------------------------------------------------------------------- ...

  3. 循环调用修正sic86

    create or replace procedure rebuild_sic86_wyl(pi_aac001 in number, po_fhz out varchar2, po_msg out v ...

  4. POJ 2208 Pyramids 欧拉四面体

    给出边长,直接就可以求出体积咯 关于欧拉四面体公式的推导及证明过程 2010-08-16 14:18 1,建议x,y,z直角坐标系.设A.B.C少拿点的坐标分别为(a1,b1,c1),(a2,b2,c ...

  5. XMPP 服务器 Openfire 的 Emoji 支持问题(进行部分修改)

    当前最新版3.9.3已经可以支持Emoji  ----------------------------------------------------------------------------- ...

  6. Linux 特殊符号使用: 倒引号`的使用

    Linux中有很多特殊符号,这里介绍 ` 倒引号的含义. 我们考虑下这个场景,有时我们需要将一个命令的执行结果赋值给某个变量,或者别的用途. 这时我们可以用两个`倒引号将该命令括起来. 例1: 如 e ...

  7. 各国iPhone5系列最新裸机价格

    美国/加拿大/中国香港/中国大陆iPhone5系列最新裸机价格

  8. POJ 3422 Kaka&#39;s Matrix Travels (最小费用最大流)

    POJ 3422 Kaka's Matrix Travels 链接:http://poj.org/problem? id=3422 题意:有一个N*N的方格,每一个方格里面有一个数字.如今卡卡要从左上 ...

  9. 手动制作rpm包

    制作RPM包的过程,简单的说,就是为制作过程提供一个“工作车间”,即一个目录,里面需要包含以下几个子目录: BUILD        ————编译相关源码包时的工作目录: RPMS         — ...

  10. 【转】CentOS上安装 jdk:rpm安装和源码安装

    1.安装 jdk-8u5-linux-x64.rpm 原文链接:http://www.cnblogs.com/xsi640/p/3756995.html 先下载最新的jdk版本 文件名:jdk-8u5 ...