使用 TarsosDSP 进行音调检测
Pitch detection using TarsosDSP
我正在尝试使用 android studio 制作应用程序。我要制作的应用程序是一个使用我们的声音的游戏。它是这样工作的。如果我唱任何 Do(或靠近 Do,例如 C#)我的车向右移动,如果我唱 Re(或可能靠近 Re)则向左移动。重点是我的应用程序首先需要识别我发出的声音。之后,如果我的声音在[Do to Do#]范围内,它就会将其识别为Do并向右移动。
我最近发现了一个可以帮助我工作的库 "TarsosDSP"。我使用了 link 上的一个示例来弄清楚它是如何工作的。我的代码就在下面
package sogangee.sibal3;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import org.w3c.dom.Text;
import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.io.android.AudioDispatcherFactory;
import be.tarsos.dsp.pitch.PitchDetectionHandler;
import be.tarsos.dsp.pitch.PitchDetectionResult;
import be.tarsos.dsp.pitch.PitchProcessor;
public class MainActivity extends AppCompatActivity {
AudioDispatcher dispatcher =
AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
TextView pitchText;
TextView noteText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pitchText = (TextView) findViewById(R.id.pitchText);
noteText = (TextView) findViewById(R.id.noteText);
PitchDetectionHandler pdh = new PitchDetectionHandler() {
@Override
public void handlePitch(PitchDetectionResult res, AudioEvent e){
final float pitchInHz = res.getPitch();
runOnUiThread(new Runnable() {
@Override
public void run() {
processPitch(pitchInHz);
}
});
}
};
AudioProcessor pitchProcessor = new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 22050, 1024, pdh);
dispatcher.addAudioProcessor(pitchProcessor);
}
public void processPitch(float pitchInHz) {
pitchText.setText("" + pitchInHz);
if(pitchInHz >= 110 && pitchInHz < 123.47) {
//A
noteText.setText("A");
}
else if(pitchInHz >= 123.47 && pitchInHz < 130.81) {
//B
noteText.setText("B");
}
else if(pitchInHz >= 130.81 && pitchInHz < 146.83) {
//C
noteText.setText("C");
}
else if(pitchInHz >= 146.83 && pitchInHz < 164.81) {
//D
noteText.setText("D");
}
else if(pitchInHz >= 164.81 && pitchInHz <= 174.61) {
//E
noteText.setText("E");
}
else if(pitchInHz >= 174.61 && pitchInHz < 185) {
//F
noteText.setText("F");
}
else if(pitchInHz >= 185 && pitchInHz < 196) {
//G
noteText.setText("G");
}
}
我正在使用 AP 21:Android 5.0 (Lollipop),我的模拟器是 NEXUS 6 API 24
我还在清单下面添加了这个词
<uses-permission android:name="android.permission.RECORD_AUDIO">
但是我有如下错误
12-04 14:28:16.598 3448-3448/sogangee.sibal3 E/AudioRecord: AudioFlinger
could not create record track, status: -1
12-04 14:28:16.602 3448-3448/sogangee.sibal3 E/AudioRecord-JNI: Error
creating AudioRecord instance: initialization check failed with status
-1.
12-04 14:28:16.603 3448-3448/sogangee.sibal3
E/android.media.AudioRecord: Error code -20 when initializing native
AudioRecord object.
12-04 14:28:16.606 3448-3448/sogangee.sibal3 E/AndroidRuntime: FATAL EXCEPTION: main
Process: sogangee.sibal3, PID: 3448
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{sogangee.sibal3/sogangee.sibal3.MainActivity}: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord.
at android.media.AudioRecord.startRecording(AudioRecord.java:976)
at be.tarsos.dsp.io.android.AudioDispatcherFactory.fromDefaultMicrophone(Unknown Source)
at sogangee.sibal3.MainActivity.<init>(MainActivity.java:20)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1078)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
我该如何解决这个问题??我还必须至少使用 android 6.0
在虚拟设备中检查应用权限。无论出于何种原因,放置 "uses-permission android:name="android.permission.RECORD_AUDIO"" 并不总是有效。
AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
不应静态调用。所以尝试调用它 in onCreate
或 after onCreate
方法。
发生此问题是因为在 API v23+ 上,您需要在运行时授予权限,而不仅仅是通过在清单文件中添加权限。
所以要修复这个错误
"startRecording() called on an uninitialized AudioRecord."
在触发任何与录音权限相关的代码之前,您需要检查是否在应用程序启动时授予了录音权限
我正在尝试使用 android studio 制作应用程序。我要制作的应用程序是一个使用我们的声音的游戏。它是这样工作的。如果我唱任何 Do(或靠近 Do,例如 C#)我的车向右移动,如果我唱 Re(或可能靠近 Re)则向左移动。重点是我的应用程序首先需要识别我发出的声音。之后,如果我的声音在[Do to Do#]范围内,它就会将其识别为Do并向右移动。 我最近发现了一个可以帮助我工作的库 "TarsosDSP"。我使用了 link 上的一个示例来弄清楚它是如何工作的。我的代码就在下面
package sogangee.sibal3;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import org.w3c.dom.Text;
import be.tarsos.dsp.AudioDispatcher;
import be.tarsos.dsp.AudioEvent;
import be.tarsos.dsp.AudioProcessor;
import be.tarsos.dsp.io.android.AudioDispatcherFactory;
import be.tarsos.dsp.pitch.PitchDetectionHandler;
import be.tarsos.dsp.pitch.PitchDetectionResult;
import be.tarsos.dsp.pitch.PitchProcessor;
public class MainActivity extends AppCompatActivity {
AudioDispatcher dispatcher =
AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
TextView pitchText;
TextView noteText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pitchText = (TextView) findViewById(R.id.pitchText);
noteText = (TextView) findViewById(R.id.noteText);
PitchDetectionHandler pdh = new PitchDetectionHandler() {
@Override
public void handlePitch(PitchDetectionResult res, AudioEvent e){
final float pitchInHz = res.getPitch();
runOnUiThread(new Runnable() {
@Override
public void run() {
processPitch(pitchInHz);
}
});
}
};
AudioProcessor pitchProcessor = new PitchProcessor(PitchProcessor.PitchEstimationAlgorithm.FFT_YIN, 22050, 1024, pdh);
dispatcher.addAudioProcessor(pitchProcessor);
}
public void processPitch(float pitchInHz) {
pitchText.setText("" + pitchInHz);
if(pitchInHz >= 110 && pitchInHz < 123.47) {
//A
noteText.setText("A");
}
else if(pitchInHz >= 123.47 && pitchInHz < 130.81) {
//B
noteText.setText("B");
}
else if(pitchInHz >= 130.81 && pitchInHz < 146.83) {
//C
noteText.setText("C");
}
else if(pitchInHz >= 146.83 && pitchInHz < 164.81) {
//D
noteText.setText("D");
}
else if(pitchInHz >= 164.81 && pitchInHz <= 174.61) {
//E
noteText.setText("E");
}
else if(pitchInHz >= 174.61 && pitchInHz < 185) {
//F
noteText.setText("F");
}
else if(pitchInHz >= 185 && pitchInHz < 196) {
//G
noteText.setText("G");
}
}
我正在使用 AP 21:Android 5.0 (Lollipop),我的模拟器是 NEXUS 6 API 24 我还在清单下面添加了这个词
<uses-permission android:name="android.permission.RECORD_AUDIO">
但是我有如下错误
12-04 14:28:16.598 3448-3448/sogangee.sibal3 E/AudioRecord: AudioFlinger could not create record track, status: -1 12-04 14:28:16.602 3448-3448/sogangee.sibal3 E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1. 12-04 14:28:16.603 3448-3448/sogangee.sibal3 E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object. 12-04 14:28:16.606 3448-3448/sogangee.sibal3 E/AndroidRuntime: FATAL EXCEPTION: main Process: sogangee.sibal3, PID: 3448 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{sogangee.sibal3/sogangee.sibal3.MainActivity}: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) Caused by: java.lang.IllegalStateException: startRecording() called on an uninitialized AudioRecord. at android.media.AudioRecord.startRecording(AudioRecord.java:976) at be.tarsos.dsp.io.android.AudioDispatcherFactory.fromDefaultMicrophone(Unknown Source) at sogangee.sibal3.MainActivity.<init>(MainActivity.java:20) at java.lang.Class.newInstance(Native Method) at android.app.Instrumentation.newActivity(Instrumentation.java:1078) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
我该如何解决这个问题??我还必须至少使用 android 6.0
在虚拟设备中检查应用权限。无论出于何种原因,放置 "uses-permission android:name="android.permission.RECORD_AUDIO"" 并不总是有效。
AudioDispatcherFactory.fromDefaultMicrophone(22050,1024,0);
不应静态调用。所以尝试调用它 in onCreate
或 after onCreate
方法。
发生此问题是因为在 API v23+ 上,您需要在运行时授予权限,而不仅仅是通过在清单文件中添加权限。 所以要修复这个错误 "startRecording() called on an uninitialized AudioRecord." 在触发任何与录音权限相关的代码之前,您需要检查是否在应用程序启动时授予了录音权限