我想在Java中混合使用多个ULAW示例。有没有一种方法可以不转换为PCM?我试图做一个8000Hz 8bit VoIP应用程序。我对所有使用ULAW编码的AU文件(在goldwave中创建)进行了即时测试。我当前的实现是:
[码]
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通道,2字节帧大小,8000帧速率,小尾数)
到ULAW(8bit 8000Hz)。
我是否做类似的事情:
1)将WAVE header 写入字节流
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();
[/码]
最佳答案
我将使用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);