Java 在android中从另一个音频文件中减去一个音频文件

Java 在android中从另一个音频文件中减去一个音频文件,java,android,algorithm,audio,audio-processing,Java,Android,Algorithm,Audio,Audio Processing,我录制了一个音频文件A并将其保存为testaudio0.gp 然后我在播放音频文件A的同时录制了一个音频文件B,并将其保存为testaudio.gp 当然,在音频文件B中,我也听到音频文件A 我在Android中使用普通的MediaPlayer和MediaRecorder类。音频文件的长度相同。两者的文件大小均为6,81Kb 这是我的密码: final MediaRecorder recorder = new MediaRecorder(); recorder.setAudioSource(Me

我录制了一个音频文件A并将其保存为testaudio0.gp 然后我在播放音频文件A的同时录制了一个音频文件B,并将其保存为testaudio.gp

当然,在音频文件B中,我也听到音频文件A

我在Android中使用普通的MediaPlayer和MediaRecorder类。音频文件的长度相同。两者的文件大小均为6,81Kb

这是我的密码:

final MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile("/sdcard/testaudio.3gp");
try {
    recorder.prepare();
} catch (IOException e) {
    e.printStackTrace();
    Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
}

Uri myUri = Uri.parse("/sdcard/testaudio0.3gp"); // initialize Uri here
final MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
    mediaPlayer.setDataSource(getApplicationContext(), myUri);
} catch (IOException e) {
    e.printStackTrace();
}
try {
    mediaPlayer.prepare();
} catch (IOException e) {
    e.printStackTrace();
}
mediaPlayer.start();




recorder.start();   // Recording is now started
new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        recorder.stop();
        recorder.reset();   // You can reuse the object by going back to setAudioSource() step
        recorder.release(); // Now the object cannot be reused
        mediaPlayer.stop();
        mediaPlayer.reset();
        mediaPlayer.release();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Recording Stopped!", Toast.LENGTH_SHORT).show();
            }
        });

    }
}, 4000);
正如您所见,我将recorder.setAudioSource更改为VOICE_通信,因为在对回声消除进行了一些研究之后,我了解到这应该会有所帮助。这似乎有点帮助,但仍然有一个非常好的背景音频文件的现有

我想减去尽可能多的音频文件A。我没有找到回答如何执行此操作的堆栈交换问题。请耐心点,我不懂那些复杂的数学运算。一个代码示例将非常有用


感谢您的帮助。谢谢。

从另一个音频文件B中减去一个音频文件A,其中B包含新信号C以及文件A的播放,这在概念上很简单。。。忽略文件B中发现的信号A从墙上反弹等的所有瑕疵。。。只需将音频曲线A的负片覆盖在音频曲线B上。。。信号A将从音频B中删除,只剩下额外的信号C

我相信您可以使用音频工作站Audacity来完成此操作。。。然而,编写自定义代码来执行相同的转换并不难。。。在伪代码中,我们将在下面执行此操作

为简单起见,让信号A从零弧度开始为正弦曲线。我们都见过这条罪恶曲线。。。若我们将这个信号合成成弧度从0到2*pi的信号,它将产生一个周期的正弦波。。。足够下面的演示了。。。现在,如果我们同时合成信号A的负值,这将发生,如果我们使用π弧度的相移,这条负曲线将是完全相反的形状

for x = 0; x < 2*pi; x += 2*pi/100 {

     A = sin(x)       // your original data of file A
  negA = sin(x + pi)  //  if you plot this negA will == A * (-1)

  new_signal = cos(5*x) // your new signal which go into file B

     B = A + new_signal // your audio data of file B

     C = B + negA  # this is same as following C = B - A == new_signal
     C = B - A     #  desired output : (signal A + new signal) minus A
                   #  this will result in simply new signal which is your goal
                   #   do you now see that C = new_signal
}

您需要深入了解数字信号处理,尤其是与音频数据和编解码器相关的信息。这更接近于写一本书长度的知识,而不是一个堆栈溢出问题。所以这是一个糟糕的问题,因为你没有足够的知识来帮助你?不,这是一个糟糕的问题,因为它需要几十页来做基础。你想要的真的很难。这个网站的范围太大了。请记住我不想要一本书。相反,我正在寻找代码的解决方案。如果有人有这方面的知识,他可能会创建一些代码并进行一些解释。这就是为什么我说:我需要代码。你录制的不仅仅是a+b,而是a转换为模拟、贯穿式扬声器、从墙上弹起、穿过麦克风,然后转换为数字+b。这样做的结果将与原来的a非常不同。取消这个是一门完整的科学。您可能会在dsp.stackexchange.com上得到一个实用的答案,但在发布之前,请先检查您的问题是否与主题相关。