I am developing an application that uses mp3 encoding/decoding. While in principle it behaves correctly for most of the files, there are some exceptions. I detected that these files have a missing header. I get an array out of bound exception when attempting to decode. I used two approaches but both failed.
The first:
DecodedMpegAudioInputStream dais = (DecodedMpegAudioInputStream) AudioSystem.getAudioInputStream(daisf, ais);
byte[] audioData = IOUtils.toByteArray(dais);//exception here
And the second:
ByteOutputStream bos = new ByteOutputStream();
// Get the decoded stream.
byte[] byteData = new byte[1];
int nBytesRead = 0;
int offset = 0;
int cnt=1;
while (nBytesRead != -1) {
System.out.println("cnt="+cnt);
nBytesRead = dais.read(byteData, offset, byteData.length);//exception here at first loop
if (nBytesRead != -1) {
int numShorts = nBytesRead >> 1;
for (int j = 0; j < numShorts; j++) {
bos.write(byteData[j]);
}
}
cnt+=1;
}
byte[] audioData = bos.getBytes();
It seems that there is an issue with the headers or the structure of it, because the dais stream has content/bytes. However it can be opened with audacity and ffplay so I believe there should be a workaround. Any ideas how to counter it?
You could use code redundancy to improve reliability. Look into alternative libraries, such as Xuggler or JLayer.
Related
I am trying to extract data from .wav file to draw a wave graph, but I am stuck as I get the only a stream of 0s with my code:
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("audio/sine_-06_05_02000.wav"));
AudioFormat format = ais.getFormat();
format = new AudioFormat(format.getFrameRate(), format.getSampleSizeInBits(), format.getChannels(), true, true);
ais = AudioSystem.getAudioInputStream(format, ais);
int sample_size = format.getSampleSizeInBits() / 8;
ArrayList<Long> data = new ArrayList<Long>();
int size = 400;
while (data.size() < size)
{
byte[] buffer = new byte[8];
ais.read(buffer, 8-sample_size, sample_size);
if (buffer[8-sample_size] < 0)
{
for (int i = 0; i < 8 - sample_size; i++)
{
buffer[i] = -1;
}
}
data.add(ByteBuffer.wrap(buffer).getLong());
}
for(long value:data)
{
System.out.println(value);
}
Please tell me why I cannot get the data and where my code is wrong if you could find out. Thank you!
Edit: I figured it out that my audio resource was digital, but the code was for analog audio.
I'm encrypting contents of a file by XORing it with a static key. Encrypting the contents varies from 100s to 200s on different android devices. Is there any way to speed up the process. Is there a way to speed up XORing bits?
byte[] buf = new byte[1024 * 1024];
byte[] cryptKey = AppUtil.KEY.getBytes();
int len;
while ((len = in.read(buf)) > 0) {
byte[] encryptedText = new byte[1024 * 1024];
for (int i = 0; i < buf.length; i++) {
encryptedText[i] = (byte) (buf[i] ^ cryptKey[i % AppUtil.KEY_SIZE]);
}
out.write(encryptedText, 0, len);
}
Since I'm working with arrays of byte, will it be better if i write this code in native? Also is there a better way than this.
Please do not suggest using AES or other algorithms. I'm not concerned with securing data, just preventing regular users from accessing specific directories of the app
I am trying to figure out a way of taking data from a file and I want to store every 4 bytes as a bitset(32). I really have no idea of how to do this. I have played about with storing each byte from the file in an array and then tried to covert every 4 bytes to a bitset but I really cannot wrap my head around using bitsets. Any ideas on how to go about this?
FileInputStream data = null;
try
{
data = new FileInputStream(myFile);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int bytesRead;
while ((bytesRead = data.read(b)) != -1)
{
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
Ok, you got your byte array. Now what you have to convert each byte to a bitset.
//Is number of bytes divisable by 4
bool divisableByFour = bytes.length % 4 == 0;
//Initialize BitSet array
BitSet[] bitSetArray = new BitSet[bytes.length / 4 + divisableByFour ? 0 : 1];
//Here you convert each 4 bytes to a BitSet
//You will handle the last BitSet later.
int i;
for(i = 0; i < bitSetArray.length-1; i++) {
int bi = i*4;
bitSetArray[i] = BitSet.valueOf(new byte[] { bytes[bi], bytes[bi+1], bytes[bi+2], bytes[bi+3]});
}
//Now handle the last BitSet.
//You do it here there may remain less than 4 bytes for the last BitSet.
byte[] lastBitSet = new byte[bytes.length - i*4];
for(int j = 0; j < lastBitSet.length; j++) {
lastBitSet[i] = bytes[i*4 + j]
}
//Put the last BitSet in your bitSetArray
bitSetArray[i] = BitSet.valueOf(lastBitSet);
I hope this works for you as I have written quickly and did not check if it works. But this gives you the basic idea, which was my intention at the beginning.
i'm want to code a method that reads part from files into byte-arrays.
for this i'm using fileinputstream and a buffered inputstream.
like this:
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
I do this only once by calling a method name "OpenFile(String File)".
Once the File has been opened with this method, i try to operate with the function: "ReadParts(byte[] buffer, int offset, int len)"
dis.read(buffer, offset, len);
for(int i = 0; i < buffer.length; i++) System.out.print((char)buffer[i]);
// used data:
// file = "C:\Temp\test.txt" with a size of 949
// buffer: always in this case with a size of 237, except for the last one its 238
// offsets: 0, 237, 474, 711
// len is always 237, except for the last one its 238
the line dis.read() throws after the first step always a indexOutOfBounds errormessage but i can't figure it out why and what. using the netbeans debugger didnt helped, since i can't find the problem with the indices.....
If you read the Stream into an array of buffers your offset and len will always have to be:
offset = 0;
len = buffer.length();
These parameters specify where the data is put in the buffer and NOT which data is read from the Stream. The Stream is read continuus (or however this gets spelled?)!
If you always call:
buffer = new byte[256];
dis.read(buffer, 0, 256);
This will happen:
Before the first call the Streamposition (position of the next byte that gets returned) is 0.
Streamposition after call=256 and buffer contains the bytes 0-255
Streamposition after call=512 and buffer contains the bytes 256-511
...
dis.reset();
Streamposition is 0 once more.
This code reads only the bytes 256-511 from a Stream into a buffer:
byte[] buffer = new byte[512];
dis.skip(256);
dis.read(buffer, 0, 256);
See that the last 256 bytes of buffer aren't filled. This is one of the differences between read(byte[], int, int) and read(byte[])!
Here are some links for you which describe the concept of a stream and the usage of read-method:
read()
Streams
how are you coming up with offset and len. My guess right now is you offset + len is greater than the buffer.
You will get IndexOutOfBoundsException - If
offset is negative,
len is negative,
len is greater than buffer.length - off
Example for point 3:
If there are 500 characters or 1500 characters in the input file, the following program will run successfully,
byte[] buffer = new byte[1000];
int offset = 0;
int len = 1000;
dis.read(buffer, offset, len);
for(int i = 0; i < buffer.length; i++) System.out.print((char)buffer[i]);
But it will fail and throw exception if,
byte[] buffer = new byte[1000];
int offset = 0;
int len = 1001;
dis.read(buffer, offset, len);
for(int i = 0; i < buffer.length; i++) System.out.print((char)buffer[i]);
Check the value of length in both the cases.
The offset is the offset in the buffer not the file.
I suspect what you want is
byte[] buffer = new byte[237];
int len = dis.read(buffer); // read another 237 bytes.
if (len < 0) throw new EOFException(); // no more data.
for(int i = 0; i < len; i++)
System.out.print((char)buffer[i]);
// or
System.out.print(new String(buffer, 0, 0, len));
In your debugger, can you check that offset >= 0 and offset + lengh <= buffer.length?
From InputStream.read()
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
One of the conditions checked for is invalid.
Recently, I've been experimenting with mixing AudioInputStreams together. After reading this post, or more importantly Jason Olson's answer, I came up with this code:
private static AudioInputStream mixAudio(ArrayList audio) throws IOException{
ArrayList<byte[]> byteArrays = new ArrayList();
long size = 0;
int pos = 0;
for(int i = 0; i < audio.size(); i++){
AudioInputStream temp = (AudioInputStream) audio.get(i);
byteArrays.add(convertStream(temp));
if(size < temp.getFrameLength()){
size = temp.getFrameLength();
pos = i;
}
}
byte[] compiledStream = new byte[byteArrays.get(pos).length];
for(int i = 0; i < compiledStream.length; i++){
int byteSum = 0;
for(int j = 0; j < byteArrays.size(); j++){
try{
byteSum += byteArrays.get(j)[i];
}catch(Exception e){
byteArrays.remove(j);
}
}
compiledStream[i] = (byte) (byteSum / byteArrays.size());
}
return new AudioInputStream(new ByteArrayInputStream(compiledStream), ((AudioInputStream)audio.get(pos)).getFormat(), ((AudioInputStream)audio.get(pos)).getFrameLength());
}
private static byte[] convertStream(AudioInputStream stream) throws IOException{
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int numRead;
while((numRead = stream.read(buffer)) != -1){
byteStream.write(buffer, 0, numRead);
}
return byteStream.toByteArray();
}
This code works very well for mixing audio files. However, it seems the more audio files being mixed, the more white noise that appears in the returned AudioInputStream. All of the files being combined are identical when it comes to formatting. If anyone has any suggestions\advice, thanks in advance.
I could be wrong, but I think your problem has to do with the fact that you are messing with the bytes instead of what the bytes mean. For instance, if you are working with a 16 bit sampling rate, 2 bytes form the number that corresponds to the amplitude rather than just 1 byte. So, you end up getting something close but not quite right.