Converting raw byte data to audio - java

In my application, I want to change the raw byte data to the audio. So, at first I receive the data and add it to a byte array list and than I want to change the whole array list to the audio. As the data is raw through audio jack, I would appreciate if you let me know which audio format is suitable (wav,3gp and so on)? Also, I have a problem with saving this data in a file. This is my code. in line of fileOuputStream.write( audiod.toArray()), it give an error and asked me to change the type of audiod to byte.
private static ArrayList<Byte> audiod = new ArrayList<Byte>();
audioFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myaudio.wav";
if (dg == 1) {
//audiod.append(data[i]);
for (int i = 0; data != null && i < data.length; i++) {
audiod.add(data[i]);
}
if (stt.equalsIgnoreCase(("r"))) {
dg = 0;
recordButton.setEnabled(true);
File file = new File(audioFilePath);
try {
FileOutputStream fileOuputStream = new FileOutputStream(audioFilePath);
fileOuputStream.write( audiod.toArray());
fileOuputStream.close();
System.out.println("Done");
}
catch(Exception e) {
e.printStackTrace();
}
}
}

audiod.toArray() will give you a Byte[], however you need a byte[]. In Java there are so called wrapper classes for the primitive data types. A Byte is an object that holds byte values.
Why do you use a list of Byte at all? It needs a lot more memory than a simple byte[] you seem to have anyhow (data).
The data format (wav,3gp and so on) depends on how you got your data.

Related

Processing Phase Cancellation on WAV file generates WAV file with no sound

So I am generating WAV file with Phase Cancellation. But generated WAV file plays but with no sound. Have used multiple players and devices but no sound. At first I copied the Header to the target file. Then,
Reading Data part of the WAV file and getting Audio Data Array
long arrLength = source.length() - Wav_header_size;
byte[] arr = new byte[(int) arrLength];
RandomAccessFile filein;
filein = new RandomAccessFile(source, "rw");
filein.seek(Wav_header_size);
filein.read();
filein.write(arr,0, arr.length);
filein.close();
Getting Channel arrays from the Audio Data
short[] shortAudioArray = new short[arr.length/2];
short[] channelLeft = new short[arr.length/4];
short[] channelRight = new short[arr.length/4];
ByteBuffer.wrap(arr).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shortAudioArray);
for(int i=0, j=0; i< shortAudioArray.length;i+=2, ++j){
if(channelLeft.length>j && channelLeft[j]!=0)
channelLeft[j] = shortAudioArray[i];
else
break;
if(channelRight.length>j && channelRight[j]!=0)
channelRight[j] = shortAudioArray[i+1];
else
break;
}
Processing Phase cancellation by negating one phase and then merging
for(int i =0;i< data2.length;i++) {
data2[i] = (short) -data2[i];
}
for(int i=0,j=0; j< dstAudio.length;i++,j=j+2) {
if(data1.length>i && data1[i]!=0)
dstAudio[j] = data1[i];
else
break;
if(data2.length>i && data2[i]!=0)
dstAudio[j+1] = data2[i];
else
break;
}
byte[] bytesLast = new byte[dstAudio.length * 2];
ByteBuffer.wrap(bytesLast).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(dstAudio);
This way same size Audio WAV file is getting generated but with no sound.
Can anyone please correct me if I am wrong in anyway in the whole process?
Java provides classes that handle the formatting and other structural aspects of the .wav file. I strongly suggest making use of those tools rather than attempting to write your own .wav headers and such.
You can read more about these tools at the Oracle tutorial on sound. The sixth in the series (Using Files and Format Converters) has a subsection on writing audio files.
So I have solved the issue by manipulating the byte array through inverting the bits one by one not producing or converting to anymore short arrays.

Reading binary file of doubles written in Java with ObjectOutputStream in Python with numpy.fromfile

I've written an array of doubles in binary format to a file using the ObjectOutputStream's writeDouble() function in Java. When I try to read this file on Python using numpy.fromfile, it doesn't give me the same values. When I try to move around in bits using seek(), it still doesn't help.
If I do the same procedure with 32 bit int, it works, but there's always a bit of the beginning of the file I need to iterate past using seek() because it's just gibberish I can't distinguish.
Relevant Java code:
//arr is an array of type double
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.bin"));
for (int i = 1; i <= 10; i++) {
out.writeDouble(arr[i]);
}
out.close();
} catch (IOException ex) {
Logger.getLogger(Project.class.getName()).log(Level.SEVERE, null, ex);
}
Relevant Python code:
datafile1 = open("data.bin", "rb")
data = np.fromfile(datafile1, dtype=np.float64, count=-1, sep='')
print data
Almost the same, but now no metadata is added to the file:
OutputStream os = new FileOutputStream("data.bin");
DataOutputStream dos = new DataOutputStream( os );
for (int i = 1; i <= 10; i++) {
dos.writeDouble(arr[i]);
}
I know it's been a few years. For posterity, here's how I got this to work with DataOutputStream.writeFloat().
As per https://stackoverflow.com/a/27681630, DataOutputStream writes in Big Endian. Numpy apparently expects binary files to be written in Little Endian, the reverse of that. The solution is to perform byteswap() on the received array.
np.fromfile('filename', np.float32).byteswap()
As you're working with doubles, I suspect you'd need to pass in np.float64 as the second argument instead. If that doesn't work, here's numpy's full list of dtypes:
https://docs.scipy.org/doc/numpy/user/basics.types.html

How to split the ByteArray by reading from the file in C++?

I have written a Java program to write the ByteArray in to a file. And that resulting ByteArray is a resulting of these three ByteArrays-
First 2 bytes is my schemaId which I have represented it using short data type.
Then next 8 Bytes is my Last Modified Date which I have represented it using long data type.
And remaining bytes can be of variable size which is my actual value for my attributes..
So I have a file now in which first line contains resulting ByteArray which will have all the above bytes as I mentioned above.. Now I need to read that file from C++ program and read the first line which will contain the ByteArray and then split that resulting ByteArray accordingly as I mentioned above such that I am able to extract my schemaId, Last Modified Date and my actual attribute value from it.
I have done all my coding always in Java and I am new to C++... I am able to write a program in C++ to read the file but not sure how should I read that ByteArray in such a way such that I am able to split it as I mentioned above..
Below is my C++ program which is reading the file and printing it out on the console..
int main () {
string line;
//the variable of type ifstream:
ifstream myfile ("bytearrayfile");
//check to see if the file is opened:
if (myfile.is_open())
{
//while there are still lines in the
//file, keep reading:
while (! myfile.eof() )
{
//place the line from myfile into the
//line variable:
getline (myfile,line);
//display the line we gathered:
// and here split the byte array accordingly..
cout << line << endl;
}
//close the stream:
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Can anyone help me with that? Thanks.
Update
Below is my java code which will write resulting ByteArray into a file and the same file now I need to read it back from c++..
public static void main(String[] args) throws Exception {
String os = "whatever os is";
byte[] avroBinaryValue = os.getBytes();
long lastModifiedDate = 1379811105109L;
short schemaId = 32767;
ByteArrayOutputStream byteOsTest = new ByteArrayOutputStream();
DataOutputStream outTest = new DataOutputStream(byteOsTest);
outTest.writeShort(schemaId);
outTest.writeLong(lastModifiedDate);
outTest.writeInt(avroBinaryValue.length);
outTest.write(avroBinaryValue);
byte[] allWrittenBytesTest = byteOsTest.toByteArray();
DataInputStream inTest = new DataInputStream(new ByteArrayInputStream(allWrittenBytesTest));
short schemaIdTest = inTest.readShort();
long lastModifiedDateTest = inTest.readLong();
int sizeAvroTest = inTest.readInt();
byte[] avroBinaryValue1 = new byte[sizeAvroTest];
inTest.read(avroBinaryValue1, 0, sizeAvroTest);
System.out.println(schemaIdTest);
System.out.println(lastModifiedDateTest);
System.out.println(new String(avroBinaryValue1));
writeFile(allWrittenBytesTest);
}
/**
* Write the file in Java
* #param byteArray
*/
public static void writeFile(byte[] byteArray) {
try{
File file = new File("bytearrayfile");
FileOutputStream output = new FileOutputStream(file);
IOUtils.write(byteArray, output);
} catch (Exception ex) {
ex.printStackTrace();
}
}
It doesn't look like you want to use std::getline to read this data. Your file isn't written as text data on a line-by-line basis - it basically has a binary format.
You can use the read method of std::ifstream to read arbitrary chunks of data from an input stream. You probably want to open the file in binary mode:
std::ifstream myfile("bytearrayfile", std::ios::binary);
Fundamentally the method you would use to read each record from the file is:
uint16_t schemaId;
uint64_t lastModifiedDate;
uint32_t binaryLength;
myfile.read(reinterpret_cast<char*>(&schemaId), sizeof(schemaId));
myfile.read(reinterpret_cast<char*>(&lastModifiedDate), sizeof(lastModifiedDate));
myfile.read(reinterpret_cast<char*>(&binaryLength), sizeof(binaryLength));
This will read the three static members of your data structure from the file. Because your data is variable size, you probably need to allocate a buffer to read it into, for example:
std::unique_ptr<char[]> binaryBuf(new char[binaryLength]);
myfile.read(binaryBuf.get(), binaryLength);
The above are examples only to illustrate how you would approach this in C++. You will need to be aware of the following things:
There's no error checking in the above examples. You'll need to check that the calls to ifstream::read are successful and return the correct amount of data.
Endianness may be an issue, depending on the the platform the data originates from and is being read on.
Interpreting the lastModifiedDate field may require you to write a function to convert it from whatever format Java uses (I have no idea about Java).

reverse chunks in a file

My basic Java problem is this: I need to read in a file by chunks, then reverse the order of the chunks, then write that out to a new file. My first (naive) attempt followed this approach:
read a chunk from the file.
reverse the bytes of the chunk
push the bytes one at a time to the front of a results list
repeat for all chunks
write result list to new file.
So this is basically a very stupid and slow way to solve the problem, but generates the correct output that I am looking for. To try to improve the situation, I change to this algorithm:
read a chunk from the file
push that chunk onto the front of a list of arrays
repeat for all chunks
foreach chunk, write to new file
And to my mind, that produces the same output. except it doesn't and I am quite confused. The first chunk in the result file matches with both methods, but the rest of the file is completely different.
Here is the meat of the Java code I am using:
FileInputStream in;
FileOutputStream out, out2;
Byte[] t = new Byte[0];
LinkedList<Byte> reversed_data = new LinkedList<Byte>();
byte[] data = new byte[bufferSize];
LinkedList<byte[]> revd2 = new LinkedList<byte[]>();
try {
in = new FileInputStream(infile);
out = new FileOutputStream(outfile1);
out2 = new FileOutputStream(outfile2);
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
while(in.read(data) != -1)
{
revd2.addFirst(data);
byte[] revd = reverse(data);
for (byte b : revd)
{
reversed_data.addFirst(b);
}
}
for (Byte b : reversed_data)
{
out.write(b);
}
for (byte[] b : revd2)
{
out2.write(b);
}
At http://pastie.org/3113665 you can see a complete example program (a long with my debugging attempts). For simplicity I am using a bufferSize that divides evenly the size of the file so all chunks will be the same size, but this won't hold in the real world. My question is, WHY don't these two methods generate the same output? It's driving me crazy because I can't grok it.
You're constantly overwriting the data you've read previously.
while(in.read(data) != -1)
{
revd2.addFirst(data);
// ignore byte-wise stuff
}
You're adding the same object repeatedly to the list revd2, so each list node will finally contain a reference to data filled with the result of the last read. I suggest replacing that with revd2.addFirst(data.clone()).
My guess is you want to change
revd2.addFirst(data);
byte[] revd = reverse(data);
for the following so the reversed copy is added to the start of the list.
byte[] revd = reverse(data);
revd2.addFirst(revd);

Convert Byte Array from Action Script to Image in Java and save it

I am a .NET Developer, but the question I am having is not related to .NET
Please keep this in mind even if my question sounds very trivial.
This is my question:
We have an swf in the browser, which communicates with a java extension
Its done using Smartfox Server(Used for MMO apllications)
From the swf we are grabbing a portion of the screen as "Byte Array" in action script(3).
And in Java, we are calling a function that converts the ByteArray to Image and then saves it.
Our Java developer is encountering the error
java.lang.illegalArgumentException
when the java function executes.
So basically, what I would like to know is this:
How to accept the object type Byte Array from ActionScript in Java?
Whats Java object type that is mapped to Byte Array in ActionScript?
The conversion part is easy, I dare say.
Update:
The code in the ActionScript Section
public function savePhoto(uName:String, ba:ByteArray, descr:String):void{
var obj:Object = {};
obj.arr = ba;
obj.desc = descr;
sfsConnectobj.photoSectionSave(obj,"save");
}
public function photoSectionSave(targetObject:Object,type:String) {
sfs.sendXtMessage("trialjava", "save", targetObject);
}
The first function calls the SmartFox Extension in Java.
The extension name is "trialjava.js"
The Java Code that accepts the function is
public void handleRequest(String cmd, ActionscriptObject ao, User u, int fromRoom)
{
try {
ActionscriptObject arr = ao.getObj("arr");
String dirName="C:\\";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(bos);
oos.writeObject(ao.getObj("arr"));
oos.flush();
oos.close();
bos.close();
byte [] data = bos.toByteArray();
BufferedImage imag=ImageIO.read(new ByteArrayInputStream(data));
ImageIO.write(imag, "jpg", new File(dirName,"snap.jpg"));
}
catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Array reading not succesful. Error is: "+e);
}
}
Seems like there was a small mismatch in retrieving the objects by java.
Now the error is different.
Array reading not succesful. Error is:
java.io.NotSerializableException:
it.goto
andplay.smartfoxserver.lib.ActionscriptObject
Regards,
naveenj
flash.utils.ByteArray is mapped to Java's byte[] type.
I am not sure if this is an issue, but according to Flash security model, if SWF is loading media from any host/domain other that the one it was loaded, screen capture would result in error.
Can you check the byte array you received? What is its size? And try to print its starting few values.
Byte array is not received directly. It comes inside an AS object. The real question here is how to get this byte array inside the ActionScript object to a Java byte array object.
I am the aforesaid Java developer and I am doing this.

Categories

Resources