混合 8 位 8000Hz PCM_ULAW 样本的最简单方法是什么?

发布于 2024-09-28 15:08:31 字数 2988 浏览 6 评论 0原文

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

[code]

    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);
    }

[/code]

如果无法直接混合 ulaw 样本并且我必须转换为 PCM,如何从 PCM 格式转换(AudioFormat.Encoding.PCM_SIGNED,8000 Hz,16bits,1通道,2 字节帧大小,8000 帧速率,小端) 至 ULAW(8 位 8000Hz)。

我是否做类似的事情: 1)将WAVE头写入字节流 2)将PCM数据写入字节流 3)使用AudioSystem.getAudioInputStream(字节流)获取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();

[/代码]

I want to mix to multiple ULAW samples together in Java. Is there a way to do so without converting to PCM? Im trying to do a 8000Hz 8bit VoIP app. Im testing with AU files (created in goldwave) since they use the ULAW encoding. My current implementation is:

[code]

    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);
    }

[/code]

If its not possible to mix the ulaw samples directly and I have to convert to PCM, how do I convert from PCM Format (AudioFormat.Encoding.PCM_SIGNED, 8000 Hz, 16bits, 1 channel, 2 byte framesize, 8000 frame rate, little endian)
to ULAW (8bit 8000Hz).

Do I do something like:
1) Write a WAVE header to a Byte stream
2) Write the PCM data to the byte stream
3) Get PCM AIS with AudioSystem.getAudioInputStream(byte stream)
4) Get ULAW Target AIS with AudioSystem.getAudioInputStream(ulawFormat, PCM AIS)

Any help is appreciated.

EDIT:
Trying to convert from Mu-LAW to PCM (Trying to use equation from http://en.wikipedia.org/wiki/Ulaw):

[CODE]

    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();

[/CODE]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

┾廆蒐ゝ 2024-10-05 15:08:31

我将使用 Wikipedia:μ- 中的公式,手动将线性编码转换为线性编码,一次一个样本法则算法

示例代码(基于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);

I would convert from/to linear encoding by hand, one sample at a time, using the formulas from Wikipedia:μ-law algorithm.

Example code (based on OP's code):

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文