Java,TargetDataLine 读取的字节,将其字节保存到文件的错误代码
Java, bytes read by TargetDataLine, Bad code saving its bytes to file
我需要对麦克风捕获的声音执行数字信号处理。
为此我做了一个Java程序,使用AudioSystem.write
保存的声音效果如预期,但我需要执行
即时处理声音。也就是说,不将其存储在文件中,为此我想获取麦克风捕获的(声音的)字节并直接处理它们。
在编写我的应用程序后,我注意到我没有得到预期的行为,所以我选择将捕获的字节存储到磁盘,并将其与 AudioSystem.write
存储进行比较,我注意到字节(有效负载,没有 WAV header) 在两个不同的文件之间。
BlockingQueue
相关的代码是因为我想用,有注释的代码是因为我在测试有没有写错。
frequency/sampleRate8192
,是我应该用的
实际上使用 AudioSystem.write
不是一个选项 因为我会花很多时间写入和重新读取光盘。我用它来证实我正在使用的字节。
public class CatchingSoundBytes {
public static void main(String[] args) {
try {
new CatchingSoundBytes().executor();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
}
}
public void executor() throws LineUnavailableException {
int numChannels = 1;
int numBytesPerSample = 2;
int sampleRate = 8192;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, true);
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioformat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
try {
targetDataLine.open(audioformat);
targetDataLine.start();
} catch (LineUnavailableException ex) {
System.out.println("ex:" + ex.getMessage());
}
int bufferSize = (int) Math.pow(2.0, 11);
final PipedOutputStream srcSavePOStream = new PipedOutputStream();
final PipedInputStream snkSavePIStream = new PipedInputStream(bufferSize);
try {
snkSavePIStream.connect(srcSavePOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
String dateFilename = new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date());
// INI Save File
new Thread(() -> {
AudioInputStream aisRecording = new AudioInputStream((InputStream) snkSavePIStream, audioformat, AudioSystem.NOT_SPECIFIED);
File fileRecordedWav = new File("Rec_" + dateFilename + ".wav");
System.out.println("fileRecordedWav:" + fileRecordedWav.getAbsolutePath());
try {
AudioSystem.write(aisRecording, AudioFileFormat.Type.WAVE, fileRecordedWav);
} catch (IOException ex) {
System.out.println("Save File -> ex:" + ex.getMessage());
}
}).start();
// END Save File
/*
PipedOutputStream rafPOStream = new PipedOutputStream();
PipedInputStream rafPIStream = new PipedInputStream(bufferSize);
try {
rafPIStream.connect(rafPOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
*/
BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>();
Stopper stopper = new Stopper();
stopper.setRunning(true);
// INI Capture Sound
new Thread(() -> {
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
int count = targetDataLine.read(buffer, 0, bufferSize);
if (count > 0) {
byte[] output = new byte[count];
System.arraycopy(buffer, 0, output, 0, count);
srcSavePOStream.write(output); // Send to Save Using AudioSystem.write
//rafPOStream.write(output);
blockingQueue.put(new BytesSound(output, index)); // Send to Save Using RandomAccessFile
}
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
}
index++;
}
targetDataLine.stop();
try {
targetDataLine.close();
} catch (SecurityException e) {
}
}).start();
// END Capture Sound
// INI Save RandomAccessFile File
new Thread(() -> {
String filename = "Raf_" + dateFilename + ".wav";
System.out.println("raf:" + filename);
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
BytesSound bytesSound = blockingQueue.take();
if (bytesSound instanceof Kill) {
break;
}
/*
rafPIStream.read(buffer);
BytesSound bytesSound = new BytesSound(buffer, index);
*/
//REALLY I don't need to save bytes in this stage,
//only in order to compare with payload of method using AudioSystem.write
// I need the bytes and position for processing
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
addSample(raf, bytesSound);
} catch (Exception ex) {
System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage());
}
index++;
}
}
).start();
// END Save RandomAccessFile File
new Timer(true).schedule(new TimerTask() {
@Override
public void run() {
stopper.setRunning(false);
}
}, 4000L);
}
private void addSample(RandomAccessFile raf, BytesSound bytesSound) {
try {
raf.seek(bytesSound.getIndex() * bytesSound.getChunk().length);
raf.write(bytesSound.getChunk());
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
}
private class BytesSound {
private final byte[] chunk;
private final long index;
public BytesSound(byte[] chunk, long index) {
this.chunk = chunk;
this.index = index;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
}
private class Kill extends BytesSound {
public Kill(byte[] chunk, long index) {
super(chunk, index);
}
}
private class Stopper {
private boolean running;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
}
我应该更改什么,才能正确地直接从麦克风中获取字节?
正在使用二进制比较器进行详细审查...
检查行 088
我用 BigEndianness
到 false
进行测试。
在 Left 侧,我使用的是 Little Endianness
,字节是:B9,FF, F6, 01
两个文件 AIS_Lit...
和 RAF_Lit...
.
我用 BigEndianness
到 true
进行测试。
但是,在右侧,
对于 AIS_Big...
文件,我有 B4, FF, 11, 02
和
对于 RAF_Big...
文件,我有 FF, B4, 02, 11
当 BigEndianness
为 true
!
时,我需要 更改取自 int count = targetDataLine.read(buffer, 0, bufferSize);
的字节顺序
另一件事,是存储 Size 文件的方式:使用 AudioSystem.write
字节不同...
也就是说,bytes 5 until 8
、存储FileSize
和bytes 41 until 44
、存储SizeData
的处理方式不同。
我在 MacBook Air 中使用 macOS Sierra (10.12),可能[=71] =] 使用 Windows 或 Linux 机器 与另一个硬件 功能工作方式不同。
现在,我的解决方案代码非常简单。
boolean endianness = false;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample,
numChannels, true, endianness);
或者使用修正的方法private byte[] endiannessReorderedBytes(byte[] incomingBytes, AudioFormat audioformat)
!
我的测试完整代码是
public class CatchingSoundBytes {
public static void main(String[] args) {
try {
new CatchingSoundBytes().executor();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
}
}
public void executor() throws LineUnavailableException {
int numChannels = 1;
int numBytesPerSample = 2;
int sampleRate = 8192;
boolean endianness = false;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, endianness);
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioformat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
try {
targetDataLine.open(audioformat);
targetDataLine.start();
} catch (LineUnavailableException ex) {
System.out.println("ex:" + ex.getMessage());
}
int bufferSize = (int) Math.pow(2.0, 11);
final PipedOutputStream srcSavePOStream = new PipedOutputStream();
final PipedInputStream snkSavePIStream = new PipedInputStream(bufferSize);
try {
snkSavePIStream.connect(srcSavePOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
String dateFilename = (endianness ? "Big" : "Lit") + new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date());
// INI Save File
new Thread(() -> {
AudioInputStream aisRecording = new AudioInputStream((InputStream) snkSavePIStream, audioformat, AudioSystem.NOT_SPECIFIED);
File fileRecordedWav = new File("AIS_" + dateFilename + ".wav");
System.out.println("fileRecordedWav:" + fileRecordedWav.getAbsolutePath());
try {
AudioSystem.write(aisRecording, AudioFileFormat.Type.WAVE, fileRecordedWav);
} catch (IOException ex) {
System.out.println("Save File -> ex:" + ex.getMessage());
}
}).start();
// END Save File
BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>();
Stopper stopper = new Stopper();
stopper.setRunning(true);
// INI Capture Sound
new Thread(() -> {
try {
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
int count = targetDataLine.read(buffer, 0, bufferSize);
if (count > 0) {
byte[] output = new byte[count];
System.arraycopy(buffer, 0, output, 0, count);
srcSavePOStream.write(output); // Send to Save Using AudioSystem.write
blockingQueue.put(new BytesSound(endiannessReorderedBytes(output, audioformat), index)); // Send to Save Using RandomAccessFile
}
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
}
index++;
if (index > 1) {
break;
}
}
targetDataLine.stop();
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
} finally {
try {
targetDataLine.close();
} catch (SecurityException e) {
}
}
}).start();
// END Capture Sound
// INI Save RandomAccessFile File
new Thread(() -> {
String filename = "RAF_" + dateFilename + ".wav";
System.out.println("raf:" + filename);
long index = 0;
while (stopper.isRunning()) {
try {
BytesSound bytesSound = blockingQueue.take();
if (bytesSound instanceof Kill) {
break;
}
//REALLY I don't need to save bytes in this stage,
//only in order to compare with payload of method using AudioSystem.write
// I need the bytes and position for processing
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
addSample(raf, bytesSound);
raf.close();
} catch (Exception ex) {
System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage());
}
index++;
if (index > 1) {
break;
}
}
System.out.println("Expected Size:" + index * bufferSize);
}
).start();
// END Save RandomAccessFile File
new Timer(true).schedule(new TimerTask() {
@Override
public void run() {
stopper.setRunning(false);
}
}, 4000L);
}
private byte[] endiannessReorderedBytes(byte[] incomingBytes, AudioFormat audioformat) {
if (!(incomingBytes != null && audioformat != null)) {
throw new IllegalArgumentException("Some arguments are null.");
}
byte[] outgoingBytes = new byte[incomingBytes.length];
if (audioformat.getSampleSizeInBits() == 16) {
if (incomingBytes.length % 2 != 0) {
throw new IllegalArgumentException("The size of the byte array does not match the audio format.");
}
int count = incomingBytes.length / 2;
if (audioformat.isBigEndian()) {
for (int i = 0; i < count; i++) {
outgoingBytes[i * 2] = incomingBytes[i * 2 + 1];
outgoingBytes[i * 2 + 1] = incomingBytes[i * 2];
}
} else {
System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
}
} else {
if (audioformat.getEncoding() == Encoding.PCM_SIGNED) {
for (int i = 0; i < incomingBytes.length; i++) {
outgoingBytes[i] = (byte) (0x80 ^ incomingBytes[i]);
}
} else {
System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
}
}
return outgoingBytes;
}
private void addSample(RandomAccessFile raf, BytesSound bytesSound) {
try {
raf.seek(44 /*Header Length*/ + bytesSound.getIndex() * bytesSound.getChunk().length);
raf.write(bytesSound.getChunk());
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
}
private class BytesSound {
private final byte[] chunk;
private final long index;
public BytesSound(byte[] chunk, long index) {
this.chunk = chunk;
this.index = index;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
}
private class Kill extends BytesSound {
public Kill(byte[] chunk, long index) {
super(chunk, index);
}
}
private class Stopper {
private boolean running;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
}
我需要对麦克风捕获的声音执行数字信号处理。
为此我做了一个Java程序,使用AudioSystem.write
保存的声音效果如预期,但我需要执行
即时处理声音。也就是说,不将其存储在文件中,为此我想获取麦克风捕获的(声音的)字节并直接处理它们。
在编写我的应用程序后,我注意到我没有得到预期的行为,所以我选择将捕获的字节存储到磁盘,并将其与 AudioSystem.write
存储进行比较,我注意到字节(有效负载,没有 WAV header) 在两个不同的文件之间。
BlockingQueue
相关的代码是因为我想用,有注释的代码是因为我在测试有没有写错。
frequency/sampleRate8192
,是我应该用的
实际上使用 AudioSystem.write
不是一个选项 因为我会花很多时间写入和重新读取光盘。我用它来证实我正在使用的字节。
public class CatchingSoundBytes {
public static void main(String[] args) {
try {
new CatchingSoundBytes().executor();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
}
}
public void executor() throws LineUnavailableException {
int numChannels = 1;
int numBytesPerSample = 2;
int sampleRate = 8192;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, true);
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioformat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
try {
targetDataLine.open(audioformat);
targetDataLine.start();
} catch (LineUnavailableException ex) {
System.out.println("ex:" + ex.getMessage());
}
int bufferSize = (int) Math.pow(2.0, 11);
final PipedOutputStream srcSavePOStream = new PipedOutputStream();
final PipedInputStream snkSavePIStream = new PipedInputStream(bufferSize);
try {
snkSavePIStream.connect(srcSavePOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
String dateFilename = new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date());
// INI Save File
new Thread(() -> {
AudioInputStream aisRecording = new AudioInputStream((InputStream) snkSavePIStream, audioformat, AudioSystem.NOT_SPECIFIED);
File fileRecordedWav = new File("Rec_" + dateFilename + ".wav");
System.out.println("fileRecordedWav:" + fileRecordedWav.getAbsolutePath());
try {
AudioSystem.write(aisRecording, AudioFileFormat.Type.WAVE, fileRecordedWav);
} catch (IOException ex) {
System.out.println("Save File -> ex:" + ex.getMessage());
}
}).start();
// END Save File
/*
PipedOutputStream rafPOStream = new PipedOutputStream();
PipedInputStream rafPIStream = new PipedInputStream(bufferSize);
try {
rafPIStream.connect(rafPOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
*/
BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>();
Stopper stopper = new Stopper();
stopper.setRunning(true);
// INI Capture Sound
new Thread(() -> {
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
int count = targetDataLine.read(buffer, 0, bufferSize);
if (count > 0) {
byte[] output = new byte[count];
System.arraycopy(buffer, 0, output, 0, count);
srcSavePOStream.write(output); // Send to Save Using AudioSystem.write
//rafPOStream.write(output);
blockingQueue.put(new BytesSound(output, index)); // Send to Save Using RandomAccessFile
}
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
}
index++;
}
targetDataLine.stop();
try {
targetDataLine.close();
} catch (SecurityException e) {
}
}).start();
// END Capture Sound
// INI Save RandomAccessFile File
new Thread(() -> {
String filename = "Raf_" + dateFilename + ".wav";
System.out.println("raf:" + filename);
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
BytesSound bytesSound = blockingQueue.take();
if (bytesSound instanceof Kill) {
break;
}
/*
rafPIStream.read(buffer);
BytesSound bytesSound = new BytesSound(buffer, index);
*/
//REALLY I don't need to save bytes in this stage,
//only in order to compare with payload of method using AudioSystem.write
// I need the bytes and position for processing
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
addSample(raf, bytesSound);
} catch (Exception ex) {
System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage());
}
index++;
}
}
).start();
// END Save RandomAccessFile File
new Timer(true).schedule(new TimerTask() {
@Override
public void run() {
stopper.setRunning(false);
}
}, 4000L);
}
private void addSample(RandomAccessFile raf, BytesSound bytesSound) {
try {
raf.seek(bytesSound.getIndex() * bytesSound.getChunk().length);
raf.write(bytesSound.getChunk());
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
}
private class BytesSound {
private final byte[] chunk;
private final long index;
public BytesSound(byte[] chunk, long index) {
this.chunk = chunk;
this.index = index;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
}
private class Kill extends BytesSound {
public Kill(byte[] chunk, long index) {
super(chunk, index);
}
}
private class Stopper {
private boolean running;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
}
我应该更改什么,才能正确地直接从麦克风中获取字节?
正在使用二进制比较器进行详细审查...
我用 BigEndianness
到 false
进行测试。
在 Left 侧,我使用的是 Little Endianness
,字节是:B9,FF, F6, 01
两个文件 AIS_Lit...
和 RAF_Lit...
.
我用 BigEndianness
到 true
进行测试。
但是,在右侧,
对于 AIS_Big...
文件,我有 B4, FF, 11, 02
和
对于 RAF_Big...
文件,我有 FF, B4, 02, 11
当 BigEndianness
为 true
!
int count = targetDataLine.read(buffer, 0, bufferSize);
的字节顺序
另一件事,是存储 Size 文件的方式:使用 AudioSystem.write
字节不同...
也就是说,bytes 5 until 8
、存储FileSize
和bytes 41 until 44
、存储SizeData
的处理方式不同。
我在 MacBook Air 中使用 macOS Sierra (10.12),可能[=71] =] 使用 Windows 或 Linux 机器 与另一个硬件 功能工作方式不同。
现在,我的解决方案代码非常简单。
boolean endianness = false;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample,
numChannels, true, endianness);
或者使用修正的方法private byte[] endiannessReorderedBytes(byte[] incomingBytes, AudioFormat audioformat)
!
我的测试完整代码是
public class CatchingSoundBytes {
public static void main(String[] args) {
try {
new CatchingSoundBytes().executor();
} catch (LineUnavailableException ex) {
ex.printStackTrace();
}
}
public void executor() throws LineUnavailableException {
int numChannels = 1;
int numBytesPerSample = 2;
int sampleRate = 8192;
boolean endianness = false;
AudioFormat audioformat = new AudioFormat(sampleRate, 8 * numBytesPerSample, numChannels, true, endianness);
DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioformat);
TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
try {
targetDataLine.open(audioformat);
targetDataLine.start();
} catch (LineUnavailableException ex) {
System.out.println("ex:" + ex.getMessage());
}
int bufferSize = (int) Math.pow(2.0, 11);
final PipedOutputStream srcSavePOStream = new PipedOutputStream();
final PipedInputStream snkSavePIStream = new PipedInputStream(bufferSize);
try {
snkSavePIStream.connect(srcSavePOStream);
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
String dateFilename = (endianness ? "Big" : "Lit") + new SimpleDateFormat("yyyyMMdd-HHmm").format(new Date());
// INI Save File
new Thread(() -> {
AudioInputStream aisRecording = new AudioInputStream((InputStream) snkSavePIStream, audioformat, AudioSystem.NOT_SPECIFIED);
File fileRecordedWav = new File("AIS_" + dateFilename + ".wav");
System.out.println("fileRecordedWav:" + fileRecordedWav.getAbsolutePath());
try {
AudioSystem.write(aisRecording, AudioFileFormat.Type.WAVE, fileRecordedWav);
} catch (IOException ex) {
System.out.println("Save File -> ex:" + ex.getMessage());
}
}).start();
// END Save File
BlockingQueue<BytesSound> blockingQueue = new LinkedBlockingQueue<>();
Stopper stopper = new Stopper();
stopper.setRunning(true);
// INI Capture Sound
new Thread(() -> {
try {
long index = 0;
byte[] buffer = new byte[bufferSize];
while (stopper.isRunning()) {
try {
int count = targetDataLine.read(buffer, 0, bufferSize);
if (count > 0) {
byte[] output = new byte[count];
System.arraycopy(buffer, 0, output, 0, count);
srcSavePOStream.write(output); // Send to Save Using AudioSystem.write
blockingQueue.put(new BytesSound(endiannessReorderedBytes(output, audioformat), index)); // Send to Save Using RandomAccessFile
}
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
}
index++;
if (index > 1) {
break;
}
}
targetDataLine.stop();
} catch (Exception ex) {
System.out.println("Capture Sound -> ex:" + ex.getMessage());
} finally {
try {
targetDataLine.close();
} catch (SecurityException e) {
}
}
}).start();
// END Capture Sound
// INI Save RandomAccessFile File
new Thread(() -> {
String filename = "RAF_" + dateFilename + ".wav";
System.out.println("raf:" + filename);
long index = 0;
while (stopper.isRunning()) {
try {
BytesSound bytesSound = blockingQueue.take();
if (bytesSound instanceof Kill) {
break;
}
//REALLY I don't need to save bytes in this stage,
//only in order to compare with payload of method using AudioSystem.write
// I need the bytes and position for processing
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
addSample(raf, bytesSound);
raf.close();
} catch (Exception ex) {
System.out.println("Save RandomAccessFile File -> ex:" + ex.getMessage());
}
index++;
if (index > 1) {
break;
}
}
System.out.println("Expected Size:" + index * bufferSize);
}
).start();
// END Save RandomAccessFile File
new Timer(true).schedule(new TimerTask() {
@Override
public void run() {
stopper.setRunning(false);
}
}, 4000L);
}
private byte[] endiannessReorderedBytes(byte[] incomingBytes, AudioFormat audioformat) {
if (!(incomingBytes != null && audioformat != null)) {
throw new IllegalArgumentException("Some arguments are null.");
}
byte[] outgoingBytes = new byte[incomingBytes.length];
if (audioformat.getSampleSizeInBits() == 16) {
if (incomingBytes.length % 2 != 0) {
throw new IllegalArgumentException("The size of the byte array does not match the audio format.");
}
int count = incomingBytes.length / 2;
if (audioformat.isBigEndian()) {
for (int i = 0; i < count; i++) {
outgoingBytes[i * 2] = incomingBytes[i * 2 + 1];
outgoingBytes[i * 2 + 1] = incomingBytes[i * 2];
}
} else {
System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
}
} else {
if (audioformat.getEncoding() == Encoding.PCM_SIGNED) {
for (int i = 0; i < incomingBytes.length; i++) {
outgoingBytes[i] = (byte) (0x80 ^ incomingBytes[i]);
}
} else {
System.arraycopy(incomingBytes, 0, outgoingBytes, 0, incomingBytes.length);
}
}
return outgoingBytes;
}
private void addSample(RandomAccessFile raf, BytesSound bytesSound) {
try {
raf.seek(44 /*Header Length*/ + bytesSound.getIndex() * bytesSound.getChunk().length);
raf.write(bytesSound.getChunk());
} catch (IOException ex) {
System.out.println("ex:" + ex.getMessage());
}
}
private class BytesSound {
private final byte[] chunk;
private final long index;
public BytesSound(byte[] chunk, long index) {
this.chunk = chunk;
this.index = index;
}
public byte[] getChunk() {
return chunk;
}
public long getIndex() {
return index;
}
}
private class Kill extends BytesSound {
public Kill(byte[] chunk, long index) {
super(chunk, index);
}
}
private class Stopper {
private boolean running;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
}
}