音乐律动Demo

来源:互联网 发布:python遗传算法工具包 编辑:程序博客网 时间:2024/04/27 13:22


本程序为用Visualizer和AudioRecord实现的音乐律动Demo,共享给大家。同时具有基本音乐播放器的雏形,可以搜索本机所有音乐,并可以切换歌曲。歌曲使用SimpleAdapter绑定在ListView上。可以随意切换歌曲。

主Activity

public class YymdActivity extends Activity {
 /**
  * 主Activity相关控件
  */
 private TextView showTitle = null, showArtist = null;
 private Button previousSong = null, playOrPause = null, nextSong = null;
 private ListView musicListView = null;
 private List<Music> musicInfos = null;

 /* 音乐频谱 */
 private MediaPlayer mMediaPlayer = null;
 private Visualizer mVisualizer = null;
 private static final int RATE = 1024;// 注意

 /* 音乐分贝 */
 private static final int SAMPLE_RATE_IN_HZ = 8000;
 private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(
   SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,
   AudioFormat.ENCODING_PCM_16BIT);
 private AudioRecord mAudioRecord = null;
 private boolean isRunning = true;
 private Object mLock;
 private static final int WAITING = 50; // 等待时间
 private Handler handler = null;

 /* 和音乐播放相关 */
 private int current_position = 0;
 private boolean isFirstTime = true;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.music);
  /* 处理通信 */
  handler = new Handler() {

   @Override
   public void handleMessage(Message msg) {
    // TODO Auto-generated method stub
    double volume = (Double) msg.obj;// 分贝值
    byte[] fft = new byte[1024];
    mVisualizer.getFft(fft);

    int color = getColor(fft);// 得到颜色值
    /* 把颜色值传出去就成了 */
    System.out.println("volume:" + volume);
    System.out.println("color:" + color);
   }

  };

  findViewsById();
  musicInfos = findMusic(this);
  initListView(musicInfos);
  musicListView.setOnItemClickListener(new OnItemClickListener() {

   public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
     long arg3) {
    // TODO Auto-generated method stub
    current_position = arg2;
    playMusic(arg2);
   }
  });

  /* 音乐频谱部分 */
  mMediaPlayer = new MediaPlayer();
  mVisualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
  mVisualizer
    .setCaptureSize(mVisualizer.getCaptureSizeRange()[mVisualizer
      .getCaptureSizeRange().length - 1]);// 注意
  mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {

   public void onCompletion(MediaPlayer mp) {
    // TODO Auto-generated method stub
    mVisualizer.setEnabled(false);
    isRunning = false;
   }
  });

  /* 处理分贝 */
  mLock = new Object();
  mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
    SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,
    AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);
  if (mAudioRecord == null) {
   Toast.makeText(this, "AudioRecord初始化失败", Toast.LENGTH_SHORT).show();
  }
 }

 /**
  * 录音分析分贝的Runnable类
  *
  * @author Leo
  *
  */
 private class RecordRunnable implements Runnable {
  public void run() {
   mAudioRecord.startRecording();
   short[] buffer = new short[BUFFER_SIZE];
   while (isRunning) {
    int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE);
    long v = 0;
    for (int i = 0; i < buffer.length; i++) {
     v += buffer[i] * buffer[i];
    }
    double mean = v / (double) r;
    double volume = 10 * Math.log10(mean);
    System.out.println("声音大小:" + volume + "分贝");

    Message msg = new Message();
    msg.obj = volume;
    handler.sendMessage(msg);

    synchronized (mLock) {
     try {
      mLock.wait(WAITING);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
   }
   mVisualizer.setEnabled(false);
   mAudioRecord.stop();
  }
 }

 /**
  * 根据频率比重最大得到颜色
  *
  * @param fft
  * @return
  */
 private int getColor(byte[] fft) {
  byte[] model = fft2Model(fft);
  int w = 0;
  byte max = model[0];
  for (int i = 1; i < model.length; i++) {
   if (model[i] > max) {
    max = model[i];
    w = i;
   }
  }
  return setColorByW(w);
 }

 /**
  * 设置颜色
  *
  * @param w
  * @return
  */
 private int setColorByW(int w) {
  int color = Color.rgb(0, 0, 0);
  switch (w % 7) {
  case 0:
   color = Color.RED;
   break;
  case 1:
   color = Color.BLUE;
   break;
  case 2:
   color = Color.GREEN;
   break;
  case 3:
   color = Color.YELLOW;
   break;
  case 4:
   color = Color.CYAN;
   break;
  case 5:
   color = Color.MAGENTA;
   break;
  case 6:
   color = Color.GREEN;
   break;
  default:
   color = Color.WHITE;
   break;
  }
  return color;
 }

 /**
  * fft转成振幅
  *
  * @param fft
  * @return
  */
 private byte[] fft2Model(byte[] fft) {
  byte[] model = new byte[fft.length / 2 + 1];
  model[0] = (byte) Math.abs(fft[0]);
  for (int i = 2, j = 1; i < fft.length - 1; i += 2, j++) {
   model[j] = (byte) Math.hypot(fft[i], fft[i + 1]);
  }
  return model;
 }

 /**
  * 把音乐绑定到ListView
  *
  * @param list
  */
 private void initListView(List<Music> list) {
  /*
   * 生成适配器并绑定到ListView上绑定监听器
   */
  List<Map<String, Object>> musicList = new ArrayList<Map<String, Object>>();
  for (Music m : list) {
   Map<String, Object> map = new HashMap<String, Object>();
   map.put("music_title", m.getTitle());
   map.put("music_artist", m.getArtist());
   musicList.add(map);
  }
  SimpleAdapter adapter = new SimpleAdapter(this, musicList,
    R.layout.music_item, new String[] { "music_title",
      "music_artist" }, new int[] { R.id.music_title,
      R.id.music_artist });
  musicListView.setAdapter(adapter);
 }

 /**
  * 根据id得到控件
  */
 private void findViewsById() {
  musicListView = (ListView) findViewById(R.id.music_listView);// 得到控件
  showTitle = (TextView) findViewById(R.id.show_title);
  showArtist = (TextView) findViewById(R.id.show_artist);
  previousSong = (Button) findViewById(R.id.previous_song);
  nextSong = (Button) findViewById(R.id.next_song);
  playOrPause = (Button) findViewById(R.id.play_pause);
  previousSong.setOnClickListener(listener);
  nextSong.setOnClickListener(listener);
  playOrPause.setOnClickListener(listener);
 }

 private View.OnClickListener listener = new View.OnClickListener() {

  public void onClick(View v) {
   // TODO Auto-generated method stub
   int id = v.getId();
   switch (id) {
   case R.id.previous_song:
    previousMusic();
    break;
   case R.id.play_pause:
    playOrPauseMusic();
    break;
   case R.id.next_song:
    nextMusic();
    break;
   default:
    Toast.makeText(YymdActivity.this, "您太厉害了,我真的不知道您按了哪个按钮",
      Toast.LENGTH_SHORT).show();
    break;
   }
  }
 };

 private void playOrPauseMusic() {
  if (mMediaPlayer == null) {
   return;
  }
  if (mMediaPlayer.isPlaying()) {
   isRunning = false;
   mMediaPlayer.pause();
   playOrPause.setText("播放");
  } else {
   if (isFirstTime) {
    playMusic(current_position);
    return;
   }
   mMediaPlayer.start();
   mVisualizer.setEnabled(true);
   isRunning = true;
   new Thread(new RecordRunnable()).start();
   playOrPause.setText("暂停");
  }
 }

 private void playMusic(int position) {
  if (mMediaPlayer == null) {
   return;
  }
  isRunning = false;
  Music music = musicInfos.get(position);
  showTitle.setText(music.getTitle());
  showArtist.setText(music.getArtist());
  try {
   mMediaPlayer.reset();
   mMediaPlayer.setDataSource(music.getData());
   mMediaPlayer.prepare();
   mMediaPlayer.start();
   isFirstTime = false;
   mVisualizer.setEnabled(true);
   isRunning = true;
   new Thread(new RecordRunnable()).start();
  } catch (IllegalArgumentException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IllegalStateException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  * 上一曲
  */
 private void previousMusic() {
  int position = current_position - 1;
  if (position < 0) {
   position = musicInfos.size() - 1;
  }
  current_position = position;
  playMusic(position);
 }

 /**
  * 下一曲
  */
 private void nextMusic() {
  int position = current_position + 1;
  if (position >= musicInfos.size()) {
   position = 0;
  }
  current_position = position;
  playMusic(position);
 }

 /**
  * 查找本地音乐放到List<Music>里面
  *
  * @param context
  * @return
  */
 private List<Music> findMusic(Context context) {
  Cursor cursor = context.getContentResolver().query(
    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
    MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
  List<Music> musicInfos = new ArrayList<Music>();
  while (cursor.moveToNext()) {
   int indexTitle = cursor
     .getColumnIndex(MediaStore.Audio.AudioColumns.TITLE);
   int indexArtist = cursor
     .getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST);
   int indexData = cursor
     .getColumnIndex(MediaStore.Audio.AudioColumns.DATA);

   String title = cursor.getString(indexTitle);
   String artist = cursor.getString(indexArtist);
   String data = cursor.getString(indexData);
   Music music = new Music();
   music.setTitle(title);
   music.setArtist(artist);
   music.setData(data);
   musicInfos.add(music);
  }
  return musicInfos;
 }

 @Override
 protected void onDestroy() {
  // TODO Auto-generated method stub
  isRunning = false;
  if (mAudioRecord != null) {
   mAudioRecord.stop();
   mAudioRecord.release();
  }
  if (mVisualizer != null) {
   if (mVisualizer.getEnabled()) {
    mVisualizer.setEnabled(false);
   }
   mVisualizer.release();
  }
  if (mMediaPlayer != null) {
   if (mMediaPlayer.isPlaying()) {
    mMediaPlayer.stop();
   }
   mMediaPlayer.release();
  }
  super.onDestroy();
 }
}

Music类:

package com.leo.yymd;

public class Music {
 private String title;
 private String artist;
 private String data;

 public String getTitle() {
  return title;
 }

 public void setTitle(String title) {
  this.title = title;
 }

 public String getArtist() {
  return artist;
 }

 public void setArtist(String artist) {
  this.artist = artist;
 }

 public String getData() {
  return data;
 }

 public void setData(String data) {
  this.data = data;
 }

}


0 0
原创粉丝点击