我目前正在尝试创建一个Android应用程序,用户按下按钮,应用程序会听取音乐,找到速度,通过以下方式从节奏中收集每个季度音符的音符信息:
这是我目前所做的代码:
package com.tentmaker.musicnotationrecorder;
import java.io.IOException;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.badlogic.gdx.audio.analysis.FFT;
public class Record extends Activity implements OnClickListener {
Button btnRecord;
private MediaRecorder mRecorder = null;
private static String mFileName = null;
float[] fftArray;
private boolean recording;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_record);
btnRecord = (Button)findViewById(R.id.recordButton);
btnRecord.setOnClickListener(this);
}
@Override
public void onClick(View v) {
try{
switch(v.getId()){
case R.id.recordButton:
buttonEvent();
return;
default:
return;
}
}
catch (Exception e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
public void buttonEvent(){
if(recording){
startRecording();
frequencyCollection();
process(fft());
}
else if(!recording){
stopRecording();
}
}
public void startRecording(){
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Toast.makeText(getApplicationContext(), "recording...", Toast.LENGTH_LONG).show();
try {
mRecorder.prepare();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "prepare() failed", Toast.LENGTH_LONG).show();
}
mRecorder.start();
}
@SuppressWarnings("unused")
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
Toast.makeText(getApplicationContext(), "done recording", Toast.LENGTH_LONG).show();
}
@SuppressWarnings("unused")
private float[] fft() {
int fs = 8374;
int N = fftArray.length;
float[] fft_cpx, tmpr, tmpi;
float[] res = new float[N / 2];
// float[] mod_spec =new float[array.length/2];
float[] real_mod = new float[N];
float[] imag_mod = new float[N];
double[] real = new double[N];
double[] imag = new double[N];
double[] mag = new double[N];
double[] phase = new double[N];
float[] new_array = new float[N];
// Zero Pad signal
for (int i = 0; i < N; i++) {
if (i < fftArray.length) {
new_array[i] = fftArray[i];
}
else {
new_array[i] = 0;
}
}
FFT fft = new FFT(N, 8373);
fft.forward(new_array);
fft_cpx = fft.getSpectrum();
tmpi = fft.getImaginaryPart();
tmpr = fft.getRealPart();
for (int i = 0; i < new_array.length; i++) {
real[i] = (double) tmpr[i];
imag[i] = (double) tmpi[i];
mag[i] = Math.sqrt((real[i] * real[i]) + (imag[i] * imag[i]));
phase[i] = Math.atan2(imag[i], real[i]);
/**** Reconstruction ****/
real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));
double freq = (double)i*(double)fs/(double)N;
Toast.makeText(getApplicationContext(),
"Frequency: "+ Double.toString(freq) +
"Magnitude: "+ Double.toString(mag[i]),
Toast.LENGTH_LONG).show();
}
fft.inverse(real_mod, imag_mod, res);
return res;
}
private void process(float[] fft){
}
@SuppressWarnings("deprecation")
private void frequencyCollection(){
int channel_config = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int format = AudioFormat.ENCODING_PCM_16BIT;
int sampleSize = 8000;
int bufferSize = AudioRecord.getMinBufferSize(sampleSize, channel_config, format);
AudioRecord audioInput = new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);
byte[] audioBuffer = new byte[bufferSize];
audioInput.startRecording();
audioInput.read(audioBuffer, 0, bufferSize);
float[] fftTempArray = new float[bufferSize];
for (int i=0; i<bufferSize; i++)
{
fftTempArray[i] = audioBuffer[i];
}
fftArray = fftTempArray;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.record, menu);
return true;
}
}
我很确定大部分都行不通。现在我正在尝试理解并完成接收字节数组并通过FFT发送它的代码。在那之后,我想从FFT得到它,并找到特定部分的最大频率(四分音符),这样我就可以完成其余部分(其中我知道该怎么做)。我该如何完成这些步骤?
答案 0 :(得分:0)
这些步骤不适用于大多数实际的现场音乐,因为大多数音乐音高都由非常复杂的FFT频率序列表示(每“四分音符”的最大频率多一个)。在mirex-IR查看很多研究生论文,了解如何在有限的案例中解决问题。