I've got a ByteArrayOutputStream
of stereo audio data. Currently I'm doing this, which I know is bad:
WaveFileWriter wfw = new WaveFileWriter();
AudioFormat format = new AudioFormat(Encoding.PCM_SIGNED, 44100, 16, 1, 2, 44100, false);
byte[] audioData = dataout.toByteArray(); //bad bad bad
int length = audioData.length;
byte[] monoData = new byte[length/2]; //bad bad bad
for(int i = 0; i < length; i+=4){
monoData[i/2] = audioData[i];
monoData[1+i/2] = audioData[i+1];
}
ByteArrayInputStream bais = new ByteArrayInputStream(monoData);
AudioInputStream outStream = new AudioInputStream(bais,format,length);
wfw.write(outStream, Type.WAVE,output);
What's a better way of doing this? Can I convert the ByteArrayOutputStream
into a ByteArrayInputStream
so that I can read from it?
Edit
Ok so I've dug into the class that's giving me the ByteArrayOutputStream
I'm working with. It's being populated with a call to:
dataout.write(convbuffer, 0, 2 * vi.channels * bout);
I can swap this out for something else if it'll help, but what should I use?
I tried replacing it with:
for(int j = 0;j < bout; j += 2){
dataout.write(convbuffer,2*j,2);
}
but that didn't work, not sure why.
Can't you read audio data by one sample at a time, and write the samples to the file as you read them?
Also it seems that your current code overwrites — Thanks for the correction, @fredley. monoData
pointlessly.
State what you're doing in plain English first; this will help you understand it, and then turn to code.
this is what I use instead of the vanilla ByteArrayOutputStream. You get a handy toByteArrayInputStream()
+ toByteBuffer()
(I tend to use quite a lot of ByteBuffers)
Hopefully many can find the code below useful, some methods are removed form the original class.
Cheers!
public class ByteBufStream extends ByteArrayOutputStream implements Serializable{
private static final long serialVersionUID = 1L;
public ByteBufStream(int initSize){
super(initSize);
}
//+few more c-tors, skipped here
public ByteArrayInputStream toByteArrayInputStream(){
return new ByteArrayInputStream(getBuf(),0, count);
}
public ByteBuffer toByteBuffer(){
return ByteBuffer.wrap(getBuf(), 0 , count);
}
public int capacity(){
return buf.length;
}
public byte[] getBuf(){
return buf;
}
public final int size() {
return count;
}
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException{
out.defaultWriteObject();
out.writeInt(capacity());
out.writeInt(size());
writeTo(out);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
in.defaultReadObject();
int capacity = in.readInt();
int size = in.readInt();
byte[] b = new byte[capacity];
for (int n=0;n<size;){
int read = in.read(b, n, size-n);
if (read<0) throw new StreamCorruptedException("can't read buf w/ size:"+size);
n+=read;
}
this.buf = b;
this.count = size;
}
}
While I generally refrain from teaching hacks, this one is probably harmless, have fun!
If you want to steal the buf[] off a vanilla ByteArrayOutputStream, look at the following method...
public synchronized void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
I guess you know what you need to do now:
class ByteArrayOutputStreamHack extends OutputStream{
public ByteArrayInputStream in;
public void write(byte b[], int off, int len) {
in = new ByteArrayInputStream(b, off, len);
}
public void write(int b){
throw new AssertionError();
}
}
ByteArrayOutputStreamHack hack = new ByteArrayOutputStreamHack()
byteArrayOutputStream.writeTo(hack);
ByteArrayInputStream in = hack.in; //we done, we cool :)
像new ByteArrayInputStream(dataout.toByteArray())
吗?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.