开发者

What is the easiest way to mix 8bit 8000Hz PCM_ULAW samples?

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);
    A开发者_JAVA技巧udioInputStream 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]


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜