0

我正在尝试在 JAVA 中构建一个“混合控制台”。在这个混音器中,每个“滑块”都是一条线,就好像它是一个物理混音控制台。但是,在我搜索 Goo*** 并阅读了oracle 文档之后,我并没有真正找到任何可以帮助我的东西。

首先,我列出了可用的混音器(见最后的代码),很高兴它列出了我所有的声卡,并找到了线路输入和线路输出。但是,我该怎么办?

我的目标是创建“虚拟线路”,它将从任何线路输入(麦克风)或线路输出(捕捉 VLC 中播放的声音)捕捉声音,让我“处理它”,然后将其重新注入另一条线路. 当然,我必须为每一行设置“输入”和“输出”的使用示例:

  • (麦克风)中的 3 条物理线路将被捕获,然后“调整电平”,然后重新注入一条称为“合唱”的虚拟线路,这条虚拟线路将重新注入我的主要物理线路,称为“大师级”。

  • VLC播放的歌曲(例如歌曲的旋律),通常直接发送到主“输出”,被捕获,就像“拦截”一样。然后我决定在将它重新注入我的Master并混合之前设置级别它与麦克风。因此,它可以让我根据音乐级别调整歌手级别。

那么,谁能帮助我开始和进步呢?谢谢你的帮助。

这是列出我的混音器的代码:

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Control;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;

public class Mixers {

Mixers() {      
    try {
        //List of the mixers from the system
        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
        //Characteristics of each mixer
        for (Mixer.Info info : mixerInfo) {
            System.out.println("\n"+info+ " - Description : "+info.getDescription());
            Mixer mix=AudioSystem.getMixer(info);

            //Controles available for this mixer
            for (Control c:mix.getControls()) {
                System.out.println ("\t Control supported by this mixer : "+c);
            }
            //Sources available for this mixer
            for (Line.Info i : mix.getSourceLineInfo()) {
                System.out.println("\t Source line available : "+i);

                //Controls available for this Source
                for (Control c : AudioSystem.getLine(i).getControls()) {
                    System.out.println ("\t\t ==> Controls supported by this source : "+c);
                }
            }
            // TargeLines available for this mixer
            for (Line.Info i : mix.getTargetLineInfo()) {
                System.out.println("\t Target line available : "+i);

                //Controls available for this Target
                for (Control c : AudioSystem.getLine(i).getControls()) {
                    System.out.println ("\t\t Controls supported by this target : "+c);
                }
            }               
        }
    } catch (Exception e) {
        e.printStackTrace();
    }               
}

}

再次感谢任何阅读我的帖子直到最后并为我提供解决方案的人。

尼古拉斯

4

2 回答 2

1

如果可以做到这一点,我认为您想要的下一步是能够从各种混合器中读取数据并在“每帧”的基础上执行操作。Java Tutorial Capturing Audio是指从外线读取数据。教程Using Files and Format Converters包含示例代码,展示了如何访问各个帧。在标题“阅读声音文件”下是示例代码。以下评论标记了最重要的一点:

// Here, do something useful with the audio data that's 
// now in the audioBytes array...

在您的情况下,您将有多个 auiodBytes 数组,每个数组用于您输入的每一行。

为了混合,可以将来自不同行的 PCM 帧数据相加。线之间的音量控制可以通过使用乘数来完成,例如,范围从0(静音)到1(全音量)的因子。

必须注意不要在单个帧中过多地更改乘数,否则引入数据的不连续性会导致点击。因此,将任何更改分散到多个帧上。乘数的线性变化与听到的音频电平不完全匹配。我认为三度指数分布通常用于在线性值和实际上听起来像这些值的等效乘数之间进行转换。您可能需要输入 min 和 max 函数以确保 PCM 数据永远不会超出范围 -1 和 1。本段的大部分内容是关于混合的精细点,并且对于最佳实践有不同的意见。

stackoverflow 上还有其他帖子介绍了如何将字节流格式转换为 PCM 格式并返回。据我所知,这段代码的源代码 javax.sound.sampled 非常依赖本机代码,而且级别很低。尽管我依赖我自己的数据源,而不是像你试图做的那样,我已经能够用这种方式做很多混合。我不知道这些外线是如何管理的,尤其是如果您希望在播放混音时让您的计算机不播放它们。

于 2015-12-20T21:48:18.447 回答
0

我不确定 java 声音 API 可以做到这一点。您可能应该查看一个低得多的 API,例如 OpenAL(Java 对此有绑定),它提供了对声音流的更多控制

于 2015-12-20T11:14:11.977 回答