简体   繁体   中英

What's a more memory-efficient way of taking part of a byte[]?

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 monoData pointlessly. — Thanks for the correction, @fredley.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM