0
我目前正在嘗試創建一個Android應用程序,其中用戶按下按鈕,應用程序收聽音樂,找到節奏,從節奏收集每個四分音符的音符信息:音樂記譜儀調試和解決(Java)
- 接收音頻字節數組。
- FFT(查找頻率)
- 使用頻率確定該四分音符的音符。
- 將該音符分配給稍後將顯示爲樂譜的數組。
這是我目前已經完成了代碼:我敢肯定大多數的這是行不通的
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中得到它並找出該特定部分的最大頻率(四分音符),以便我可以完成剩下的工作(我知道該怎麼做)。我應該如何完成這些步驟?
現在我想看看是否可以用單音符組成的簡單旋律來做這樣的事情。這是可能的使用這些步驟,或者甚至是這個簡單的要求研究生水平的項目? – JoshSchellenberger
如果你的旋律是由一個由嚴格節奏計時器驅動的正弦波發生器產生的話,可能是合理的。 – hotpaw2
那麼你會推薦我做什麼? – JoshSchellenberger