【问题标题】:What is the easiest way to mix 8bit 8000Hz PCM_ULAW samples?混合 8 位 8000Hz PCM_ULAW 样本的最简单方法是什么?
【发布时间】:2014-03-18 16:53:24
【问题描述】:

我想在 Java 中将多个 ULAW 样本混合在一起。有没有办法在不转换为 PCM 的情况下这样做?我正在尝试做一个 8000Hz 8bit VoIP 应用程序。我使用 AU 文件(在 goldwave 中创建)进行测试,因为它们使用 ULAW 编码。我目前的实现是:

[代码]

    AudioFormat f = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 2, 8000, false);
    SourceDataLine sdl = AudioSystem.getSourceDataLine(f);
    sdl.open(f);
    sdl.start();

    File file1 = new File("C:\\Scream3.au");
    AudioInputStream ais1 = AudioSystem.getAudioInputStream(file1);
    AudioInputStream aisTarget1 = AudioSystem.getAudioInputStream(f, ais1);

    File file2 = new File("C:\\Blackout3.au");
    AudioInputStream ais2 = AudioSystem.getAudioInputStream(file2);
    AudioInputStream aisTarget2 = AudioSystem.getAudioInputStream(f, ais2);

    byte[] data = new byte[10000];
    int[] calc = new int[5000];
    AudioInputStream[] streams = {aisTarget1, aisTarget2};
    int count = streams.length + 1;
    while (true) {
        int r = -1;
        for (int i = 0; i < streams.length; i++) {
            r = streams[i].read(data, 0, data.length);
            if (r == -1) break;
            for (int j = 0; j < calc.length; j++) {
                int tempVal = ((data[j * 2 + 1] << 8) | (data[j * 2] & 0xFF));
                calc[j] += tempVal;
            }
        }
        for (int i = 0; i < calc.length; i++) {
            calc[i] /= count;
            data[i * 2 + 0] = (byte) (calc[i] & 0xFF);
            data[i * 2 + 1] = (byte) (calc[i] >> 8);
        }
        if (r == -1) break;
        sdl.write(data, 0, data.length);
    }

[/代码]

如果不能直接混合 ulaw 样本并且我必须转换为 PCM,我如何从 PCM 格式转换(AudioFormat.Encoding.PCM_SIGNED, 8000 Hz, 16bits, 1 channel, 2 byte framesize, 8000 frame rate , 小端) 到 ULAW (8bit 8000Hz)。

我是否会这样做: 1) 将 WAVE 头写入字节流 2)将PCM数据写入字节流 3) 使用 AudioSystem.getAudioInputStream(byte stream) 获取 PCM AIS 4) 使用 AudioSystem.getAudioInputStream(ulawFormat, PCM AIS) 获取 ULAW 目标 AIS

感谢任何帮助。

编辑: 尝试从 Mu-LAW 转换为 PCM(尝试使用来自http://en.wikipedia.org/wiki/Ulaw 的方程):

[代码]

    AudioFormat f = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 8, 1, 1, 8000, false);
    SourceDataLine sdl = AudioSystem.getSourceDataLine(f);
    sdl.open(f);
    sdl.start();
    File file1 = new File("C:\\scream3.au");
    FileInputStream fis = new FileInputStream(file1);
    // Skip header
    fis.skip(24);
    byte[] data = new byte[8196];

    while (true) {
        int r = fis.read(data, 0, data.length);
        if (r == -1) break;
        for (int i = 0; i < r; i++) {
            float y = ((float) data[i] / Byte.MAX_VALUE);
            float sample = -1.0f * (float) (Math.signum(y) * (1.0f / 255.0f) * (Math.pow(1 + 255, Math.abs(y)) - 1.0f));
            data[i] = (byte) (sample * Byte.MAX_VALUE);
        }
        sdl.write(data, 0, data.length);
    }
    sdl.drain();
    sdl.stop();
    sdl.close();
    fis.close();

[/代码]

【问题讨论】:

    标签: java audio voip


    【解决方案1】:

    我会使用Wikipedia:μ-law algorithm 中的公式手动转换线性编码,一次一个样本。

    示例代码(基于 OP 的代码):

    float sample1 = Math.signum(y1)/255.0*(Math.pow(256, Math.abs(y1))-1);
    float sample2 = Math.signum(y2)/255.0*(Math.pow(256, Math.abs(y2))-1);
    float combined = somethig * sample1 + (1-something) * sample2;
    float result = Math.signum(combined)*Math.log(1+255*Math.abs(combined))/Math.log(256);
    

    【讨论】:

    • 感谢您的回复!我正在尝试这样做,不幸的是我的数学不太好。你能帮帮我吗?
    • 这与转换为 PCM 并返回有何不同?
    • @Gabe:一样的。我只是说你不需要写头,使用字节流等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多