Problem:
I want to send an image from matlab to android over bluetooth.
Matlab and android are connected to each other and I can send strings without a problem.
fprintf(tabletObj, 'sleep');
I have a really huge byteArray containing the image I want to send to android. Here you can see just the first bytes:
planString = [-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,72,0,0,0,72,8,6,0,0,0,85,-19,-77,71,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,-120,0,0,29,2,73,68,65,84,120,-100,-75,-100,121,-68,37, ... ]
After that, I set in matlab the OutputBufferSize to the size of the image and send it to the tablet.
s = whos('planString');
obj1.OutputBufferSize = s.bytes;
% Send it to tablet
fwrite(tabletObj, planString, 'int8');
In android you can see following incoming bytes.
Why are there just the first 6 bytes and not more?
The next incoming bytes are more then just 6 bytes, why?
I set the buffersize in android to the same size like matlab.
private void listen() {
byte[] buffer = new byte[picSize]; // buffer store for the stream
Log.i(TAG, "buffer length" + buffer.length);
while (true) {
try {
inputStream.read(buffer);
newMessageReceived(new String(buffer, "UTF-8")); // Send the obtained bytes to the UI activity
} catch (IOException e) {
break;
}
}
}
Edit #1:
I used following code to get only the "right" bytes and put that into an ArrayList with bytes. Now, it seems like that I have just the needed bytes. But it's too slow! You need to wait for more than 1 min. to get all bytes from matlab. Is there a better solution? Why are the incoming bytes split sometimes in 3, sometimes in 15, ...? (see picture below code)
ArrayList<byte[]> bytes = new ArrayList<byte[]>();
...
int nread = inputStream.read(buffer);
byte[] newOne = new byte[nread];
System.arraycopy(buffer, 0, newOne, 0, nread);
bytes.add(newOne);
private void listen() {
byte[] buffer = new byte[10000];
int nbytes = 0;
while (true) {
try {
int nread = inputStream.read(buffer, nbytes, buffer.length - nbytes);
nbytes += nread;
... // after getting all bytes
newMessageReceived(buffer, nbytes); // Send bytes to the UI activity
} catch (IOException e) {
break;
}
}
}
#greenapps thanks for the solution.
Related
I have to upload big video files to a server, but it's taking too long to upload, so I decided to split/chunk the files and then send them to the server
After splitting my files, I get a response like the following:
[ /storage/emulated/0/1493357699.mp4.001, /storage/emulated/0/1493357699.mp4.002, /storage/emulated/0/1493357699.mp4.003, /storage/emulated/0/1493357699.mp4.004, /storage/emulated/0/1493357699.mp4.005, /storage/emulated/0/1493357699.mp4.006, /storage/emulated/0/1493357699.mp4.007, /storage/emulated/0/1493357699.mp4.008 ]
My thought is what is the use to upload spitting/chunk file to server?
My code for splitting files:
public static List<File> splitFile(File f) {
try {
int partCounter = 1;
List<File> result = new ArrayList<>();
int sizeOfFiles = 1024 * 1024;// 1MB
byte[] buffer = new byte[sizeOfFiles];
// create a buffer of bytes sized as the one chunk size
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
String name = f.getName();
int tmp = 0;
while ((tmp = bis.read(buffer)) > 0) {
File newFile = new File(f.getParent(), name + "." + String.format("%03d", partCounter++));
// naming files as <inputFileName>.001, <inputFileName>.002, ...
FileOutputStream out = new FileOutputStream(newFile);
out.write(buffer, 0, tmp);//tmp is chunk size. Need it for the last chunk,
// which could be less then 1 mb.
result.add(newFile);
}
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
I have implemented in one of my projects. I see two primary reasons:
To achieve multi-threaded / multiple connection for uploading chunks. You can upload multiple chunks at the same time.
Stop/Resume uploading of rest of the chunks if either of the chunk fails to upload (depending on server response)
I am trying to create a chat application between Android and a Windows 10 device.
I have successfully sent text from Android using DataOutputStream and read it in Windows 10 using a data reader class.
My problem is Android is not able to recognize the text from Windows. It displays the result of the datainputstream.available() function but the application hangs in case I use the readString() or the readbyte() function.
Code in Android for receiving:
DataInputStream dIn = new DataInputStream(clientSocket.getInputStream());
if(dIn.available()>0)
{
int length = dIn.readInt(); // app hangs in here
byte[] byteReceived = new byte[length];
dIn.readFully(byteReceived, 0 , length); // sometimes app hangs here
String textReceived = new String(byteReceived);
text.setText(Client Says: "+ textReceived + "\n");//
}
Data sent from Windows through datawriter:
DataWriter writer = new DataWriter(socket.OutputStream))
{
writer.UnicodeEncoding=windows.Storage.Streams.UnicodeEncoding.Utf8;
writer.ByteOrder = windows.Storage.Streams.ByteOrder.LittleEndian;
uint size =writer.MeasureString(message);
writer.WriteUint32(size);
writer.WriteString(message);
try
{
await writer.StoreAsync();
}
catch (Exception exception)
{
switch (SocketError.GetStatus(exception.HResult))
{
case SocketErrorStatus.HostNotFound:
// Handle HostNotFound Error
throw;
default:
throw;
}
}
await writer.FlushAsync();
writer.DetachStream();
}
What is the issue here?
Your dIn.readFully expects bytes and not String. Moreover, it expects the exact number of bytes, as length variable. You need to create bytes from String on the windows size and send the length of byte array as Int in first transaction. Then you need to transfer this byte array unchanged in second transaction. Try it.
I am trying to read a wav file into an array using Android. In order to validate the results I read the same wav file using Matlab. The problem is that the values are different. Your help is highly appreciated in solving this problem.
Kindly, find below the Matlab and Android code with the associated results:
Matlab Code:
fName = 'C:\Users\me\Desktop\audioText.txt';
fid = fopen(fName,'w');
dlmwrite(fName,y_sub,'-append','delimiter','\t','newline','pc');
Matlab Results:
0.00097656
0.00045776
0.0010681
0.00073242
0.00054932
-0.00064087
0.0010376
-0.00027466
-0.00036621
-9.1553e-05
0.00015259
0.0021362
-0.00024414
-3.0518e-05
-0.00021362
Android Code:
String filePath;
private static DataOutputStream fout;
ByteArrayOutputStream out;
BufferedInputStream in;
filePath = "mnt/sdcard/audio.wav";
out = new ByteArrayOutputStream();
try {
in = new BufferedInputStream(new FileInputStream(filePath));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
int read;
byte[] buff = new byte[2000000];
try {
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
out.flush();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
byte[] audioBytes = out.toByteArray();
}
Android Results:
82, 73, 70, 70, 92, 108, 40, 0, 87, 65, 86, 69, 102, 109
Thanks,
In Android you're reading the file header, not the actual values of the sound samples. Your values in Android are ASCII for
RIFF\l( WAVEfm
In Matlab I'm not sure what you're doing... looks like you're writing, not reading a file.
The dir command is quite helpful here. It either displays the whole content of a directory but you can also specify a glob to just return a sub-set of files, e.g. dir('*.wav'). This returns an struct-array containing file information such as name, date, bytes, isdir and so on.
To get started, try the following:
filelist = dir('*.wav');
for file = filelist
fprintf('Processing %s\n', file.name);
fid = fopen(file.name);
% Do something here with your file.
fclose(fid);
end
If a processing result has to be stored per file,
I often use the following pattern. I usually pre-allocate an array, a struct array or
a cell array of the same size as the filelist. Then I use an integer index to iterate
over the file list, which I can also use to write the output. If the information to be
stored is homogeneous (e.g. one scalar per file), use an array or a struct array.
However, if the information differs from file to file (e.g. vectors or matrices of different size) use a cell array instead.
An example using an ordinary array:
filelist = dir('*.wav');
% Pre-allocate an array to store some per-file information.
result = zeros(size(filelist));
for index = 1 : length(filelist)
fprintf('Processing %s\n', filelist(index).name);
% Read the sample rate Fs and store it.
[y, Fs] = wavread(filelist(index).name);
result(index) = Fs;
end
% result(1) .. result(N) contain the sample rates of each file.
An example using a cell array:
filelist = dir('*.wav');
% Pre-allocate a cell array to store some per-file information.
result = cell(size(filelist));
for index = 1 : length(filelist)
fprintf('Processing %s\n', filelist(index).name);
% Read the data of the WAV file and store it.
y = wavread(filelist(index).name);
result{index} = y;
end
% result{1} .. result{N} contain the data of the WAV files.
I am not sure what is the problem exactly, but I got the correct readings when I used the following code:
File filein = new File(filePath, "audio.wav");
try
{
// Open the wav file specified as the first argument
WavFile wavFile = WavFile.openWavFile(filein);
// Display information about the wav file
wavFile.display();
// Get the number of audio channels in the wav file
int numChannels = wavFile.getNumChannels();
// Create a buffer of 100 frames
double[] buffer = new double[20000 * numChannels];
int framesRead;
double min = Double.MAX_VALUE;
double max = Double.MIN_VALUE;
do
{
// Read frames into buffer
framesRead = wavFile.readFrames(buffer, 20000);
// Loop through frames and look for minimum and maximum value
for (int s=0 ; s<framesRead * numChannels ; s++)
{
if (buffer[s] > max) max = buffer[s];
if (buffer[s] < min) min = buffer[s];
}
}
while (framesRead != 0);
// Close the wavFile
wavFile.close();
// Output the minimum and maximum value
System.out.printf("Min: %f, Max: %f\n", min, max);
}
catch (Exception e)
{
System.err.println(e);
}
I am reading values from a wav file; selecting only some of those values and writing them into another wav file (inorder to remove silence periods from the wav file). The problem is, that when I am creating this new wav file, it has background noise (which is not present in the original wav file). I am adding here the part of the code which is doing the file writing part:
private void writeToFile(String filePath) {
short nChannels = 1;
int sRate = 16000;
short bSamples = 16;
audioShorts = new short[size];
int nSamples = 0;
for(int i=0; i<size-1; i++) {
//audioShorts[i] = Short.reverseBytes((short)(zff[i]*0x8000));
if(slope[i] >= slopeThreshold) { // Voice region -- Should be written to output
audioShorts[nSamples] = Short.reverseBytes((short)(a[i]*0x8000));
audioShorts[nSamples+1] = Short.reverseBytes((short)(a[i+1]*0x8000));
nSamples += 2;
i++;
}
/*else
audioShorts[i] = 0;*/
}
finalShorts = new short[nSamples];
for(int i=0; i<nSamples; i++){
finalShorts[i] = audioShorts[i];
}
data = new byte[finalShorts.length*2];
ByteBuffer buffer = ByteBuffer.wrap(data);
ShortBuffer sbuf = buffer.asShortBuffer();
sbuf.put(finalShorts);
data = buffer.array();
Log.d("Data length------------------------------", Integer.toString(data.length));
RandomAccessFile randomAccessWriter;
try {
randomAccessWriter = new RandomAccessFile(filePath, "rw");
randomAccessWriter.setLength(0); // Set file length to 0, to prevent unexpected behaviour in case the file already existed
randomAccessWriter.writeBytes("RIFF");
randomAccessWriter.writeInt(Integer.reverseBytes(36+data.length)); // File length
randomAccessWriter.writeBytes("WAVE");
randomAccessWriter.writeBytes("fmt ");
randomAccessWriter.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM
randomAccessWriter.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM
randomAccessWriter.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo
randomAccessWriter.writeInt(Integer.reverseBytes(sRate)); // Sample rate
randomAccessWriter.writeInt(Integer.reverseBytes(sRate*bSamples*nChannels/8)); // Byte rate, SampleRate*NumberOfChannels*BitsPerSample/8
randomAccessWriter.writeShort(Short.reverseBytes((short)(nChannels*bSamples/8))); // Block align, NumberOfChannels*BitsPerSample/8
randomAccessWriter.writeShort(Short.reverseBytes(bSamples)); // Bits per sample
randomAccessWriter.writeBytes("data");
randomAccessWriter.writeInt(Integer.reverseBytes(data.length)); // No. of samples
randomAccessWriter.write(data);
randomAccessWriter.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Your code snippet leaves some details out (like what slope and slopeThreshold are), so treat this answer as a suggestion only.
In general, this kind of chopping of audio data will introduce noise. It depends on where the cut happens. If the last sample before a cut is identical to the first one after it, you're safe, but otherwise you will introduce a click.
If the cuts are infrequent, you will be hearing individual clicks but if the chopping happens often enough, it might sound like continuous noise.
To do this without clicks, you would need to add a short fade out and fade in around each cut.
EDIT: try removing the "if (slope[i] >= slopeThreshold)" condition and see if the noise disappears. If so, the noise is very likely a result of what I described. Otherwise, you probably have some error with the various byte conversions.
Instead of:
data = new byte[finalShorts.length*2];
ByteBuffer buffer = ByteBuffer.wrap(data);
ShortBuffer sbuf = buffer.asShortBuffer();
sbuf.put(finalShorts);
data = buffer.array();
would not it be necessary to convert from short [] to byte [] ?
data = shortToBytes(finalShorts);
public byte [] shortToBytes(short [] input){
int short_index, byte_index;
int iterations = input.length;
byte [] buffer = new byte[input.length * 2];
short_index = byte_index = 0;
for(/*NOP*/; short_index != iterations; /*NOP*/)
{
buffer[byte_index] = (byte) (input[short_index] & 0x00FF);
buffer[byte_index + 1] = (byte) ((input[short_index] & 0xFF00) >> 8);
++short_index; byte_index += 2;
}
return buffer;
}
This work for me.
I'm trying to transfer about a megabyte of arbitrary data at a time from one android phone to another. Currently, I write the size, a command code and the data to a DataOutputStream around a BufferedOutputStream, around the OutputStream returned from bluetoothSocketInstance.getOutputStream().
The receiving phone reads the size and command code and then reads from the input stream until it has gotten all the data it is expecting. This works for short strings, but for larger files not all the data is transferred. Running the app in the debugger shows that the write returns without any exceptions and the read reads a fraction of the bytes expected and then blocks indefinitely. It also does not throw any exceptions.
Is there a buffer somewhere that is filling up? Is there something else I need to do to ensure that all the data gets transferred?
My code for the sender and receiver are below:
Sender:
try {
DataOutputStream d = new DataOutputStream(new BufferedOutputStream(mmOutStream,buffer.length+8));
//int b= buffer.length;
d.writeInt(buffer.length);
d.writeInt(command);
d.write(buffer);
d.flush();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
Receiver:
try {
// Read from the InputStream
int messageSize= inStream.readInt();
int messageCode = inStream.readInt();
bytes=0;
buffer =new byte[messageSize];
while(bytes < messageSize)
{
bytes += inStream.read(buffer,bytes,messageSize - bytes);
}
message = bytes;
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
After some more testing on my end, I changed my sending code to look like this:
for(int i=0; i<buffer.length;i+=BIG_NUM)
{
int b = ((i+BIG_NUM) < buffer.length) ? BIG_NUM: buffer.length - i;
d.write(buffer,i,b);
d.flush();
}
The files now get sent. Does anyone have an idea why? Does the call to flush() block until the data has actually been transferred? Is there any documentation about the size of the send and receive buffers that would help me to decide how large I can safely make BIG_NUM?
I have similar problem, when sending file there are some parts missing. I try BufferedOutputStream but problem still exist.
Finally i find simple solution:
You don't need to send buffer length, just split sending buffer to byte array (for example [8192]) and on receive side make sure that this buffer is much bigger about 4 or 8 times than sending buffer. This worked for me and file is sent completed.