Android : Read binary file failure - java

I was try to read a binary file storing the position of x, y, z ,w.
that is, they are all float such as 1.4567896 5.156986 .....etc.
I successfully read it in c++ and also java, but couldn't done in android,
all I read in is all zero...
Here is my code :
ps. I try many codes before, all failed...
public class DataIO {
private int DataSize = 640*320*4;
private float[] fDataBuffer;
private byte[] bDataBuffer;
private String sOutput;
public DataIO(){
bDataBuffer = new byte[DataSize*4];
fDataBuffer = new float[DataSize];
}
/*=============================================
* Function:
* ReadFile
* Description:
* Read binary float data to float[] buffer.
*================================================ */
public void ReadFile(String FileName){
File file = new File(FileName);
try {
FileInputStream finStream = new FileInputStream(file);
if(finStream.read(bDataBuffer) == -1){
Log.d("ReadData", "Reading Data has problem.");
}
finStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int index = 0;
for(int i = 0; i < DataSize; i+=1){
/*int asInt = (bDataBuffer[i+0] & 0xFF)
| ((bDataBuffer[i+1] & 0xFF) << 8)
| ((bDataBuffer[i+2] & 0xFF) << 16)
| ((bDataBuffer[i+3] & 0xFF) << 24);
fDataBuffer[index] = Float.intBitsToFloat(asInt);*/
sOutput += String.format("%d ", bDataBuffer[i]);
index++;
}
}
/*=============================================
* Function:
* GetData
* Description:
* output the data by string.
*================================================ */
public String GetData(){
return sOutput;
}
}
I blocked the transformation of byte to float cuz read in byte have to be check if they are correct first.

On Android you need to use a runnable interface to constantly check a variable.

Related

Finding time difference between two audio spikes? [duplicate]

How can I detect silence when recording operation is started in Java? What is PCM data? How can I calculate PCM data in Java?
I found the solution :
package bemukan.voiceRecognition.speechToText;
import javax.sound.sampled.*;
import java.io.*;
public class RecordAudio {
private File audioFile;
protected boolean running;
private ByteArrayOutputStream out;
private AudioInputStream inputStream;
final static float MAX_8_BITS_SIGNED = Byte.MAX_VALUE;
final static float MAX_8_BITS_UNSIGNED = 0xff;
final static float MAX_16_BITS_SIGNED = Short.MAX_VALUE;
final static float MAX_16_BITS_UNSIGNED = 0xffff;
private AudioFormat format;
private float level;
private int frameSize;
public RecordAudio(){
getFormat();
}
private AudioFormat getFormat() {
File file = new File("src/Facebook/1.wav");
AudioInputStream stream;
try {
stream = AudioSystem.getAudioInputStream(file);
format=stream.getFormat();
frameSize=stream.getFormat().getFrameSize();
return stream.getFormat();
} catch (UnsupportedAudioFileException e) {
} catch (IOException e) {
}
return null;
}
public void stopAudio() {
running = false;
}
public void recordAudio() {
try {
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];
public void run() {
int readPoint = 0;
out = new ByteArrayOutputStream();
running = true;
int sum=0;
while (running) {
int count =
line.read(buffer, 0, buffer.length);
calculateLevel(buffer,0,0);
System.out.println(level);
if (count > 0) {
out.write(buffer, 0, count);
}
}
line.stop();
}
};
Thread captureThread = new Thread(runner);
captureThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}
public File getAudioFile() {
byte[] audio = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
try {
final AudioFormat format = getFormat();
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("temp.wav"));
input.close();
System.out.println("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
return new File("temp.wav");
}
private void calculateLevel (byte[] buffer,
int readPoint,
int leftOver) {
int max = 0;
boolean use16Bit = (format.getSampleSizeInBits() == 16);
boolean signed = (format.getEncoding() ==
AudioFormat.Encoding.PCM_SIGNED);
boolean bigEndian = (format.isBigEndian());
if (use16Bit) {
for (int i=readPoint; i<buffer.length-leftOver; i+=2) {
int value = 0;
// deal with endianness
int hiByte = (bigEndian ? buffer[i] : buffer[i+1]);
int loByte = (bigEndian ? buffer[i+1] : buffer [i]);
if (signed) {
short shortVal = (short) hiByte;
shortVal = (short) ((shortVal << 8) | (byte) loByte);
value = shortVal;
} else {
value = (hiByte << 8) | loByte;
}
max = Math.max(max, value);
} // for
} else {
// 8 bit - no endianness issues, just sign
for (int i=readPoint; i<buffer.length-leftOver; i++) {
int value = 0;
if (signed) {
value = buffer [i];
} else {
short shortVal = 0;
shortVal = (short) (shortVal | buffer [i]);
value = shortVal;
}
max = Math.max (max, value);
} // for
} // 8 bit
// express max as float of 0.0 to 1.0 of max value
// of 8 or 16 bits (signed or unsigned)
if (signed) {
if (use16Bit) { level = (float) max / MAX_16_BITS_SIGNED; }
else { level = (float) max / MAX_8_BITS_SIGNED; }
} else {
if (use16Bit) { level = (float) max / MAX_16_BITS_UNSIGNED; }
else { level = (float) max / MAX_8_BITS_UNSIGNED; }
}
} // calculateLevel
}
How can I detect silence when recording operation is started in Java?
Calculate the dB or RMS value for a group of sound frames and decide at what level it is considered to be 'silence'.
What is PCM data?
Data that is in Pulse-code modulation format.
How can I calculate PCM data in Java?
I do not understand that question. But guessing it has something to do with the speech-recognition tag, I have some bad news. This might theoretically be done using the Java Speech API. But there are apparently no 'speech to text' implementations available for the API (only 'text to speech').
I have to calculate rms for speech-recognition project. But I do not know how can I calculate in Java.
For a single channel that is represented by signal sizes in a double ranging from -1 to 1, you might use this method.
/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
public double volumeRMS(double[] raw) {
double sum = 0d;
if (raw.length==0) {
return sum;
} else {
for (int ii=0; ii<raw.length; ii++) {
sum += raw[ii];
}
}
double average = sum/raw.length;
double sumMeanSquare = 0d;
for (int ii=0; ii<raw.length; ii++) {
sumMeanSquare += Math.pow(raw[ii]-average,2d);
}
double averageMeanSquare = sumMeanSquare/raw.length;
double rootMeanSquare = Math.sqrt(averageMeanSquare);
return rootMeanSquare;
}
There is a byte buffer to save input values from the line, and what I should have to do with this buffer?
If using the volumeRMS(double[]) method, convert the byte values to an array of double values ranging from -1 to 1. ;)
You need to catch the value like a number silence is zero or near
Please adapt your code to your requirement!!!
In this case a variable named UMBRAL (Threshold in spanish)...
Suppose that you have access to WAV file like bytes ByteHeader...
private Integer Byte2PosIntBig(byte Byte24, byte Byte16, byte Byte08, byte Byte00) {
return new Integer (
((Byte24) << 24)|
((Byte16 & 0xFF) << 16)|
((Byte08 & 0xFF) << 8)|
((Byte00 & 0xFF) << 0));
}
Before ....
RandomAccessFile RAFSource = new RandomAccessFile("your old file wav", "r");
Begins here...
int PSData = 44;
byte[] Bytes = new byte[4];
byte[] ByteHeader = new byte[44];
RAFSource.seek(0);
RAFSource.read(ByteHeader);
int WavSize = Byte2PosIntBig(ByteHeader[43],ByteHeader[42],ByteHeader[41],ByteHeader[40]);
int NumBits = Byte2PosIntBig(ByteHeader[35],ByteHeader[34]);
int NumByte = NumBits/8;
for (int i = PSData;i < PSData+WavSize;i+=NumByte) {
int WavSample = 0;
int WavResultI =0;
int WavResultO = 0;
if (NumByte == 2) {
RAFSource.seek(i);
Bytes[0] = RAFSource.readByte();
Bytes[1] = RAFSource.readByte();
WavSample = (int)(((Bytes[1]) << 8)|((Bytes[0] & 0xFF) << 0));
if (Math.abs(WavSample) < UMBRAL) {
//SILENCE DETECTED!!!
}
} else {
RAFSource.seek(i);
WavSample = (short)(RAFSource.readByte() & 0xFF);
short sSamT = (short)WavSample;
sSamT += 128;
double dSamD = (double)sSamT*Multiplier;
if ((double)sSamT < UMBRAL) {
//SILENCE DETECTED!!!
}
}

Android ContentProvider openFile: need to serve "modified" file

I want to serve image files that saved on "external storage" via ContentProvider.
These image files are 'mangled' - first 50 bytes are XORed with some arbitary value. I want to do 'demangle' within ContentProvider so that other applications don't need to do special treatment.
I'm using Mininum SDK version 14.
Here is my first try - using piped ParcelFileDescriptor:
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
// basic uri/mode check here
return openPipeHelper(uri, getType(uri), null, new FileInputStream(getImageFile(uri)), new PipeDataWriter<InputStream>() {
#Override
public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, final String mimeType, Bundle opts, InputStream input) {
InputStream fin = new FilterInputStream(input) {
private int cnt = 0;
private byte mask;
#Override
public int read() throws IOException {
byte[] buffer = new byte[1];
return read(buffer) == -1 ? -1 : (buffer[0] & 0xff);
}
#Override
public int read(#NonNull byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
#Override
public int read(#NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
int ret = super.read(buffer, byteOffset, byteCount);
if (ret <= 0) return ret;
if (cnt == 0) {
switch (mimeType) {
case "image/png":
mask = (byte) (buffer[byteOffset] ^ 137);
break;
case "image/webp":
mask = (byte) (buffer[byteOffset] ^ 'R');
break;
}
}
for (int i = byteOffset; i < byteOffset + ret && cnt < 50; i++, cnt++) {
buffer[i] ^= mask;
}
return ret;
}
};
OutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(output);
byte[] buf = new byte[1024 * 1024];
try {
while (true) {
int n = fin.read(buf);
if (n == -1) break;
Log.i(TAG, "openFile get n=" + n);
fout.write(buf, 0, n);
fout.flush();
}
} catch (IOException ex) {
// EPIPE likely means pipe closed on other end; treat it as WAI.
if (!ex.getMessage().contains("EPIPE")) {
Log.w(TAG, "openFile failed", ex);
}
} finally {
try {
fin.close();
} catch (IOException ex) {
Log.w(TAG, "openFile failed closing input", ex);
}
try {
fout.close();
} catch (IOException ex) {
Log.w(TAG, "openFile failed closing output", ex);
}
}
}
});
}
Result:
Works well with ImageView.setImageURI().
Don't work with android default Gallery (Intent.ACTION_VIEW with setDataAndType())
Works well with ES image viewer
It seems that Gallery don't like "piped stream".
Here is second try - read whole file, demangle, and serve as ParcelFileDescriptor.fromData():
File file = getImageFile(uri);
byte[] buffer = readFully(file);
String mimeType = getType(uri);
byte mask;
switch (mimeType) {
case "image/png":
mask = (byte) (buffer[0] ^ 137);
break;
case "image/webp":
mask = (byte) (buffer[0] ^ 'R');
break;
default:
mask = 0;
break;
}
for (int i = 0; i < 50; i++) buffer[i] ^= mask;
return (ParcelFileDescriptor) ParcelFileDescriptor.class.getMethod("fromData", byte[].class, String.class).invoke(null, buffer, getImageFile(uri).getName());
Result:
Don't work well with ImageView.setImageURI().
Works well with android default Gallery
Works well with ES image viewer
It seems that from time to time, MemoryFile made in ParcelFileDescriptor.fromData() is closed and disposed before ImageView.setImageURI() get data.
Here is third try - write demangled image to temporary file:
// buffer contains readFully and demangled image binary
try {
File tmpFile = File.createTempFile("image", getImageExtension(uri));
OutputStream os = new FileOutputStream(tmpFile);
try {
os.write(buffer);
} finally {
try {
os.close();
} catch (IOException ex2) {
Log.w(TAG, "openFile(): closing failed", ex2);
}
}
return ParcelFileDescriptor.open(tmpFile, ParcelFileDescriptor.MODE_READ_ONLY);
} catch (IOException ex2) {
Log.e(TAG, "openFile(): writing failed", ex2);
return null;
}
Result:
Works well with ImageView.setImageURI().
Works well with android default Gallery
Works well with ES image viewer
However, I don't like this solution, as it is very hard to determine when I could delete temporary files.
These 3 solutions have their flaws, and I couldn't find flawless solution. What is the "right" way to do such things?

sending png image file from server (desktop) to client (android) via socket programming

I've created an android application in which the Android application acts as the client and server resides on a desktop. I'm using socket programming for communication. I've successfully transferred messages between client and server, but I don't know how to transfer an image. I need to send image file from server to client, not from client to server
Can anyone please help me with the solution for sending a png image from server to client?
This is my code so far:
Client side
private int SERVER_PORT = 9999;
class Client implements Runnable {
private Socket client;
private PrintWriter out;
private Scanner in;
#Override
public void run() {
try {
client = new Socket("localhost", SERVER_PORT);
Log.d("Client", "Connected to server at port " + SERVER_PORT);
out = new PrintWriter(client.getOutputStream());
in = new Scanner(client.getInputStream());
String line;
while ((line = in.nextLine()) != null) {
Log.d("Client", "Server says: " + line);
if (line.equals("Hello client")) {
out.println("Reply");
out.flush();
}
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Server class
class ServerThread implements Runnable {
private ServerSocket server;
#Override
public void run() {
try {
server = new ServerSocket(SERVER_PORT);
Log.d("Server", "Start the server at port " + SERVER_PORT
+ " and waiting for clients...");
while (true) {
Socket socket = server.accept();
Log.d("Server",
"Accept socket connection: "
+ socket.getLocalAddress());
new Thread(new ClientHandler(socket)).start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandler implements Runnable {
private Socket clientSocket;
private PrintWriter out;
private Scanner in;
public ClientHandler(Socket clietSocket) {
this.clientSocket = clietSocket;
}
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream());
in = new Scanner(clientSocket.getInputStream());
String line;
Log.d("ClientHandlerThread", "Start communication with : "
+ clientSocket.getLocalAddress());
out.println("Hello client");
out.flush();
while ((line = in.nextLine()) != null) {
Log.d("ClientHandlerThread", "Client says: " + line);
if (line.equals("Reply")){
out.print("Server replies");
out.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here you have server and client codes that send/receive (image) files from server to client.
Client save the image in external storage, change that if you want to save it somewhere else.
The client function returns a Bitmap of the received image, you can also avoid this by commenting the lines in the code.
To use the functions, use something similar to the following: NOTE these two function must be called from a thread other than the main UI thread:
// To receive a file
try
{
// The file name must be simple file name, without file separator '/'
receiveFile(myClientSocket.getInputStream(), "myImage.png");
}
catch (Exception e)
{
e.printStackTrace();
}
// to send a file
try
{
// The file name must be a fully qualified path
sendFile(myServerSocket.getOutputStream(), "C:/MyImages/orange.png");
}
catch (Exception e)
{
e.printStackTrace();
}
The receiver function: (Copy and paste it to the client side)
/**
* Receive an image file from a connected socket and save it to a file.
* <p>
* the first 4 bytes it receives indicates the file's size
* </p>
*
* #param is
* InputStream from the connected socket
* #param fileName
* Name of the file to save in external storage, without
* File.separator
* #return Bitmap representing the image received o null in case of an error
* #throws Exception
* #see {#link sendFile} for an example how to send the file at other side.
*
*/
public Bitmap receiveFile(InputStream is, String fileName) throws Exception
{
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileInES = baseDir + File.separator + fileName;
// read 4 bytes containing the file size
byte[] bSize = new byte[4];
int offset = 0;
while (offset < bSize.length)
{
int bRead = is.read(bSize, offset, bSize.length - offset);
offset += bRead;
}
// Convert the 4 bytes to an int
int fileSize;
fileSize = (int) (bSize[0] & 0xff) << 24
| (int) (bSize[1] & 0xff) << 16
| (int) (bSize[2] & 0xff) << 8
| (int) (bSize[3] & 0xff);
// buffer to read from the socket
// 8k buffer is good enough
byte[] data = new byte[8 * 1024];
int bToRead;
FileOutputStream fos = new FileOutputStream(fileInES);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (fileSize > 0)
{
// make sure not to read more bytes than filesize
if (fileSize > data.length) bToRead = data.length;
else bToRead = fileSize;
int bytesRead = is.read(data, 0, bToRead);
if (bytesRead > 0)
{
bos.write(data, 0, bytesRead);
fileSize -= bytesRead;
}
}
bos.close();
// Convert the received image to a Bitmap
// If you do not want to return a bitmap comment/delete the folowing lines
// and make the function to return void or whatever you prefer.
Bitmap bmp = null;
FileInputStream fis = new FileInputStream(fileInES);
try
{
bmp = BitmapFactory.decodeStream(fis);
return bmp;
}
finally
{
fis.close();
}
}
The sender function: (copy and paste it to the server side)
/**
* Send a file to a connected socket.
* <p>
* First it sends file size in 4 bytes then the file's content.
* </p>
* <p>
* Note: File size is limited to a 32bit signed integer, 2GB
* </p>
*
* #param os
* OutputStream of the connected socket
* #param fileName
* The complete file's path of the image to send
* #throws Exception
* #see {#link receiveFile} for an example how to receive file at other side.
*
*/
public void sendFile(OutputStream os, String fileName) throws Exception
{
// File to send
File myFile = new File(fileName);
int fSize = (int) myFile.length();
if (fSize < myFile.length())
{
System.out.println("File is too big'");
throw new IOException("File is too big.");
}
// Send the file's size
byte[] bSize = new byte[4];
bSize[0] = (byte) ((fSize & 0xff000000) >> 24);
bSize[1] = (byte) ((fSize & 0x00ff0000) >> 16);
bSize[2] = (byte) ((fSize & 0x0000ff00) >> 8);
bSize[3] = (byte) (fSize & 0x000000ff);
// 4 bytes containing the file size
os.write(bSize, 0, 4);
// In case of memory limitations set this to false
boolean noMemoryLimitation = true;
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
try
{
if (noMemoryLimitation)
{
// Use to send the whole file in one chunk
byte[] outBuffer = new byte[fSize];
int bRead = bis.read(outBuffer, 0, outBuffer.length);
os.write(outBuffer, 0, bRead);
}
else
{
// Use to send in a small buffer, several chunks
int bRead = 0;
byte[] outBuffer = new byte[8 * 1024];
while ((bRead = bis.read(outBuffer, 0, outBuffer.length)) > 0)
{
os.write(outBuffer, 0, bRead);
}
}
os.flush();
}
finally
{
bis.close();
}
}

Detect silence when recording

How can I detect silence when recording operation is started in Java? What is PCM data? How can I calculate PCM data in Java?
I found the solution :
package bemukan.voiceRecognition.speechToText;
import javax.sound.sampled.*;
import java.io.*;
public class RecordAudio {
private File audioFile;
protected boolean running;
private ByteArrayOutputStream out;
private AudioInputStream inputStream;
final static float MAX_8_BITS_SIGNED = Byte.MAX_VALUE;
final static float MAX_8_BITS_UNSIGNED = 0xff;
final static float MAX_16_BITS_SIGNED = Short.MAX_VALUE;
final static float MAX_16_BITS_UNSIGNED = 0xffff;
private AudioFormat format;
private float level;
private int frameSize;
public RecordAudio(){
getFormat();
}
private AudioFormat getFormat() {
File file = new File("src/Facebook/1.wav");
AudioInputStream stream;
try {
stream = AudioSystem.getAudioInputStream(file);
format=stream.getFormat();
frameSize=stream.getFormat().getFrameSize();
return stream.getFormat();
} catch (UnsupportedAudioFileException e) {
} catch (IOException e) {
}
return null;
}
public void stopAudio() {
running = false;
}
public void recordAudio() {
try {
final AudioFormat format = getFormat();
DataLine.Info info = new DataLine.Info(
TargetDataLine.class, format);
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
line.open(format);
line.start();
Runnable runner = new Runnable() {
int bufferSize = (int) format.getSampleRate()
* format.getFrameSize();
byte buffer[] = new byte[bufferSize];
public void run() {
int readPoint = 0;
out = new ByteArrayOutputStream();
running = true;
int sum=0;
while (running) {
int count =
line.read(buffer, 0, buffer.length);
calculateLevel(buffer,0,0);
System.out.println(level);
if (count > 0) {
out.write(buffer, 0, count);
}
}
line.stop();
}
};
Thread captureThread = new Thread(runner);
captureThread.start();
} catch (LineUnavailableException e) {
System.err.println("Line unavailable: " + e);
System.exit(-2);
}
}
public File getAudioFile() {
byte[] audio = out.toByteArray();
InputStream input = new ByteArrayInputStream(audio);
try {
final AudioFormat format = getFormat();
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("temp.wav"));
input.close();
System.out.println("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
return new File("temp.wav");
}
private void calculateLevel (byte[] buffer,
int readPoint,
int leftOver) {
int max = 0;
boolean use16Bit = (format.getSampleSizeInBits() == 16);
boolean signed = (format.getEncoding() ==
AudioFormat.Encoding.PCM_SIGNED);
boolean bigEndian = (format.isBigEndian());
if (use16Bit) {
for (int i=readPoint; i<buffer.length-leftOver; i+=2) {
int value = 0;
// deal with endianness
int hiByte = (bigEndian ? buffer[i] : buffer[i+1]);
int loByte = (bigEndian ? buffer[i+1] : buffer [i]);
if (signed) {
short shortVal = (short) hiByte;
shortVal = (short) ((shortVal << 8) | (byte) loByte);
value = shortVal;
} else {
value = (hiByte << 8) | loByte;
}
max = Math.max(max, value);
} // for
} else {
// 8 bit - no endianness issues, just sign
for (int i=readPoint; i<buffer.length-leftOver; i++) {
int value = 0;
if (signed) {
value = buffer [i];
} else {
short shortVal = 0;
shortVal = (short) (shortVal | buffer [i]);
value = shortVal;
}
max = Math.max (max, value);
} // for
} // 8 bit
// express max as float of 0.0 to 1.0 of max value
// of 8 or 16 bits (signed or unsigned)
if (signed) {
if (use16Bit) { level = (float) max / MAX_16_BITS_SIGNED; }
else { level = (float) max / MAX_8_BITS_SIGNED; }
} else {
if (use16Bit) { level = (float) max / MAX_16_BITS_UNSIGNED; }
else { level = (float) max / MAX_8_BITS_UNSIGNED; }
}
} // calculateLevel
}
How can I detect silence when recording operation is started in Java?
Calculate the dB or RMS value for a group of sound frames and decide at what level it is considered to be 'silence'.
What is PCM data?
Data that is in Pulse-code modulation format.
How can I calculate PCM data in Java?
I do not understand that question. But guessing it has something to do with the speech-recognition tag, I have some bad news. This might theoretically be done using the Java Speech API. But there are apparently no 'speech to text' implementations available for the API (only 'text to speech').
I have to calculate rms for speech-recognition project. But I do not know how can I calculate in Java.
For a single channel that is represented by signal sizes in a double ranging from -1 to 1, you might use this method.
/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
public double volumeRMS(double[] raw) {
double sum = 0d;
if (raw.length==0) {
return sum;
} else {
for (int ii=0; ii<raw.length; ii++) {
sum += raw[ii];
}
}
double average = sum/raw.length;
double sumMeanSquare = 0d;
for (int ii=0; ii<raw.length; ii++) {
sumMeanSquare += Math.pow(raw[ii]-average,2d);
}
double averageMeanSquare = sumMeanSquare/raw.length;
double rootMeanSquare = Math.sqrt(averageMeanSquare);
return rootMeanSquare;
}
There is a byte buffer to save input values from the line, and what I should have to do with this buffer?
If using the volumeRMS(double[]) method, convert the byte values to an array of double values ranging from -1 to 1. ;)
You need to catch the value like a number silence is zero or near
Please adapt your code to your requirement!!!
In this case a variable named UMBRAL (Threshold in spanish)...
Suppose that you have access to WAV file like bytes ByteHeader...
private Integer Byte2PosIntBig(byte Byte24, byte Byte16, byte Byte08, byte Byte00) {
return new Integer (
((Byte24) << 24)|
((Byte16 & 0xFF) << 16)|
((Byte08 & 0xFF) << 8)|
((Byte00 & 0xFF) << 0));
}
Before ....
RandomAccessFile RAFSource = new RandomAccessFile("your old file wav", "r");
Begins here...
int PSData = 44;
byte[] Bytes = new byte[4];
byte[] ByteHeader = new byte[44];
RAFSource.seek(0);
RAFSource.read(ByteHeader);
int WavSize = Byte2PosIntBig(ByteHeader[43],ByteHeader[42],ByteHeader[41],ByteHeader[40]);
int NumBits = Byte2PosIntBig(ByteHeader[35],ByteHeader[34]);
int NumByte = NumBits/8;
for (int i = PSData;i < PSData+WavSize;i+=NumByte) {
int WavSample = 0;
int WavResultI =0;
int WavResultO = 0;
if (NumByte == 2) {
RAFSource.seek(i);
Bytes[0] = RAFSource.readByte();
Bytes[1] = RAFSource.readByte();
WavSample = (int)(((Bytes[1]) << 8)|((Bytes[0] & 0xFF) << 0));
if (Math.abs(WavSample) < UMBRAL) {
//SILENCE DETECTED!!!
}
} else {
RAFSource.seek(i);
WavSample = (short)(RAFSource.readByte() & 0xFF);
short sSamT = (short)WavSample;
sSamT += 128;
double dSamD = (double)sSamT*Multiplier;
if ((double)sSamT < UMBRAL) {
//SILENCE DETECTED!!!
}
}

Windows shortcut (.lnk) parser in Java?

I'm currently using Win32ShellFolderManager2 and ShellFolder.getLinkLocation to resolve windows shortcuts in Java. Unfortunately, if the Java program is running as a service under Vista, getLinkLocation, this does not work. Specifically, I get an exception stating "Could not get shell folder ID list".
Searching the web does turn up mentions of this error message, but always in connection with JFileChooser. I'm not using JFileChooser, I just need to resolve a .lnk file to its destination.
Does anyone know of a 3rd-party parser for .lnk files written in Java I could use?
I've since found unofficial documentation for the .lnk format here, but I'd rather not have to do the work if anyone has done it before, since the format is rather scary.
Added comments (some explanation as well as credit to each contributor so far),additional check on the file magic, a quick test to see if a given file might be a valid link (without reading all of the bytes), a fix to throw a ParseException with appropriate message instead of ArrayIndexOutOfBoundsException if the file is too small, did some general clean-up.
Source here (if you have any changes, push them right to the GitHub repo/project.
package org.stackoverflowusers.file;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
/**
* Represents a Windows shortcut (typically visible to Java only as a '.lnk' file).
*
* Retrieved 2011-09-23 from http://stackoverflow.com/questions/309495/windows-shortcut-lnk-parser-in-java/672775#672775
* Originally called LnkParser
*
* Written by: (the stack overflow users, obviously!)
* Apache Commons VFS dependency removed by crysxd (why were we using that!?) https://github.com/crysxd
* Headerified, refactored and commented by Code Bling http://stackoverflow.com/users/675721/code-bling
* Network file support added by Stefan Cordes http://stackoverflow.com/users/81330/stefan-cordes
* Adapted by Sam Brightman http://stackoverflow.com/users/2492/sam-brightman
* Based on information in 'The Windows Shortcut File Format' by Jesse Hager <jessehager#iname.com>
* And somewhat based on code from the book 'Swing Hacks: Tips and Tools for Killer GUIs'
* by Joshua Marinacci and Chris Adamson
* ISBN: 0-596-00907-0
* http://www.oreilly.com/catalog/swinghks/
*/
public class WindowsShortcut
{
private boolean isDirectory;
private boolean isLocal;
private String real_file;
/**
* Provides a quick test to see if this could be a valid link !
* If you try to instantiate a new WindowShortcut and the link is not valid,
* Exceptions may be thrown and Exceptions are extremely slow to generate,
* therefore any code needing to loop through several files should first check this.
*
* #param file the potential link
* #return true if may be a link, false otherwise
* #throws IOException if an IOException is thrown while reading from the file
*/
public static boolean isPotentialValidLink(File file) throws IOException {
final int minimum_length = 0x64;
InputStream fis = new FileInputStream(file);
boolean isPotentiallyValid = false;
try {
isPotentiallyValid = file.isFile()
&& file.getName().toLowerCase().endsWith(".lnk")
&& fis.available() >= minimum_length
&& isMagicPresent(getBytes(fis, 32));
} finally {
fis.close();
}
return isPotentiallyValid;
}
public WindowsShortcut(File file) throws IOException, ParseException {
InputStream in = new FileInputStream(file);
try {
parseLink(getBytes(in));
} finally {
in.close();
}
}
/**
* #return the name of the filesystem object pointed to by this shortcut
*/
public String getRealFilename() {
return real_file;
}
/**
* Tests if the shortcut points to a local resource.
* #return true if the 'local' bit is set in this shortcut, false otherwise
*/
public boolean isLocal() {
return isLocal;
}
/**
* Tests if the shortcut points to a directory.
* #return true if the 'directory' bit is set in this shortcut, false otherwise
*/
public boolean isDirectory() {
return isDirectory;
}
/**
* Gets all the bytes from an InputStream
* #param in the InputStream from which to read bytes
* #return array of all the bytes contained in 'in'
* #throws IOException if an IOException is encountered while reading the data from the InputStream
*/
private static byte[] getBytes(InputStream in) throws IOException {
return getBytes(in, null);
}
/**
* Gets up to max bytes from an InputStream
* #param in the InputStream from which to read bytes
* #param max maximum number of bytes to read
* #return array of all the bytes contained in 'in'
* #throws IOException if an IOException is encountered while reading the data from the InputStream
*/
private static byte[] getBytes(InputStream in, Integer max) throws IOException {
// read the entire file into a byte buffer
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buff = new byte[256];
while (max == null || max > 0) {
int n = in.read(buff);
if (n == -1) {
break;
}
bout.write(buff, 0, n);
if (max != null)
max -= n;
}
in.close();
return bout.toByteArray();
}
private static boolean isMagicPresent(byte[] link) {
final int magic = 0x0000004C;
final int magic_offset = 0x00;
return link.length >= 32 && bytesToDword(link, magic_offset) == magic;
}
/**
* Gobbles up link data by parsing it and storing info in member fields
* #param link all the bytes from the .lnk file
*/
private void parseLink(byte[] link) throws ParseException {
try {
if (!isMagicPresent(link))
throw new ParseException("Invalid shortcut; magic is missing", 0);
// get the flags byte
byte flags = link[0x14];
// get the file attributes byte
final int file_atts_offset = 0x18;
byte file_atts = link[file_atts_offset];
byte is_dir_mask = (byte)0x10;
if ((file_atts & is_dir_mask) > 0) {
isDirectory = true;
} else {
isDirectory = false;
}
// if the shell settings are present, skip them
final int shell_offset = 0x4c;
final byte has_shell_mask = (byte)0x01;
int shell_len = 0;
if ((flags & has_shell_mask) > 0) {
// the plus 2 accounts for the length marker itself
shell_len = bytesToWord(link, shell_offset) + 2;
}
// get to the file settings
int file_start = 0x4c + shell_len;
final int file_location_info_flag_offset_offset = 0x08;
int file_location_info_flag = link[file_start + file_location_info_flag_offset_offset];
isLocal = (file_location_info_flag & 2) == 0;
// get the local volume and local system values
//final int localVolumeTable_offset_offset = 0x0C;
final int basename_offset_offset = 0x10;
final int networkVolumeTable_offset_offset = 0x14;
final int finalname_offset_offset = 0x18;
int finalname_offset = link[file_start + finalname_offset_offset] + file_start;
String finalname = getNullDelimitedString(link, finalname_offset);
if (isLocal) {
int basename_offset = link[file_start + basename_offset_offset] + file_start;
String basename = getNullDelimitedString(link, basename_offset);
real_file = basename + finalname;
} else {
int networkVolumeTable_offset = link[file_start + networkVolumeTable_offset_offset] + file_start;
int shareName_offset_offset = 0x08;
int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset]
+ networkVolumeTable_offset;
String shareName = getNullDelimitedString(link, shareName_offset);
real_file = shareName + "\\" + finalname;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new ParseException("Could not be parsed, probably not a valid WindowsShortcut", 0);
}
}
private static String getNullDelimitedString(byte[] bytes, int off) {
int len = 0;
// count bytes until the null character (0)
while (true) {
if (bytes[off + len] == 0) {
break;
}
len++;
}
return new String(bytes, off, len);
}
/*
* convert two bytes into a short note, this is little endian because it's
* for an Intel only OS.
*/
private static int bytesToWord(byte[] bytes, int off) {
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
}
private static int bytesToDword(byte[] bytes, int off) {
return (bytesToWord(bytes, off + 2) << 16) | bytesToWord(bytes, off);
}
}
Sam Brightman's solution is for local files only.
I added support for Network files:
Windows shortcut (.lnk) parser in Java?
http://code.google.com/p/8bits/downloads/detail?name=The_Windows_Shortcut_File_Format.pdf
http://www.javafaq.nu/java-example-code-468.html
public class LnkParser {
public LnkParser(File f) throws IOException {
parse(f);
}
private boolean isDirectory;
private boolean isLocal;
public boolean isDirectory() {
return isDirectory;
}
private String real_file;
public String getRealFilename() {
return real_file;
}
private void parse(File f) throws IOException {
// read the entire file into a byte buffer
FileInputStream fin = new FileInputStream(f);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buff = new byte[256];
while (true) {
int n = fin.read(buff);
if (n == -1) {
break;
}
bout.write(buff, 0, n);
}
fin.close();
byte[] link = bout.toByteArray();
parseLink(link);
}
private void parseLink(byte[] link) {
// get the flags byte
byte flags = link[0x14];
// get the file attributes byte
final int file_atts_offset = 0x18;
byte file_atts = link[file_atts_offset];
byte is_dir_mask = (byte)0x10;
if ((file_atts & is_dir_mask) > 0) {
isDirectory = true;
} else {
isDirectory = false;
}
// if the shell settings are present, skip them
final int shell_offset = 0x4c;
final byte has_shell_mask = (byte)0x01;
int shell_len = 0;
if ((flags & has_shell_mask) > 0) {
// the plus 2 accounts for the length marker itself
shell_len = bytes2short(link, shell_offset) + 2;
}
// get to the file settings
int file_start = 0x4c + shell_len;
final int file_location_info_flag_offset_offset = 0x08;
int file_location_info_flag = link[file_start + file_location_info_flag_offset_offset];
isLocal = (file_location_info_flag & 2) == 0;
// get the local volume and local system values
//final int localVolumeTable_offset_offset = 0x0C;
final int basename_offset_offset = 0x10;
final int networkVolumeTable_offset_offset = 0x14;
final int finalname_offset_offset = 0x18;
int finalname_offset = link[file_start + finalname_offset_offset] + file_start;
String finalname = getNullDelimitedString(link, finalname_offset);
if (isLocal) {
int basename_offset = link[file_start + basename_offset_offset] + file_start;
String basename = getNullDelimitedString(link, basename_offset);
real_file = basename + finalname;
} else {
int networkVolumeTable_offset = link[file_start + networkVolumeTable_offset_offset] + file_start;
int shareName_offset_offset = 0x08;
int shareName_offset = link[networkVolumeTable_offset + shareName_offset_offset]
+ networkVolumeTable_offset;
String shareName = getNullDelimitedString(link, shareName_offset);
real_file = shareName + "\\" + finalname;
}
}
private static String getNullDelimitedString(byte[] bytes, int off) {
int len = 0;
// count bytes until the null character (0)
while (true) {
if (bytes[off + len] == 0) {
break;
}
len++;
}
return new String(bytes, off, len);
}
/*
* convert two bytes into a short note, this is little endian because it's
* for an Intel only OS.
*/
private static int bytes2short(byte[] bytes, int off) {
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
}
/**
* Returns the value of the instance variable 'isLocal'.
*
* #return Returns the isLocal.
*/
public boolean isLocal() {
return isLocal;
}
}
I can recommend this repository on GitHub:
https://github.com/BlackOverlord666/mslinks
There I've found a simple solution to create shortcuts:
ShellLink.createLink("path/to/existing/file.txt", "path/to/the/future/shortcut.lnk");
If you want to read shortcuts:
File shortcut = ...;
String pathToExistingFile = new ShellLink(shortcut).resolveTarget();
If you want to change the icon of the shortcut, use:
ShellLink sl = ...;
sl.setIconLocation("/path/to/icon/file");
You can edit most properties of the shortcutlink such as working directory, tooltip text, icon, command line arguments, hotkeys, create links to LAN shared files and directories and much more...
Hope this helps you :)
Kind regards
Josua Frank
The code plan9assembler linked to appears to work with minor modification. I think it's just the "& 0xff" to prevent sign extension when bytes are upcast to ints in the bytes2short function that need changing. I've added the functionality described in http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf to concatenate the "final part of the pathname" even though in practice this doesn't seem to be used in my examples. I've not added any error checking to the header or dealt with network shares. Here's what I'm using now:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
public class LnkParser {
public LnkParser(File f) throws Exception {
parse(f);
}
private boolean is_dir;
public boolean isDirectory() {
return is_dir;
}
private String real_file;
public String getRealFilename() {
return real_file;
}
private void parse(File f) throws Exception {
// read the entire file into a byte buffer
FileInputStream fin = new FileInputStream(f);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buff = new byte[256];
while (true) {
int n = fin.read(buff);
if (n == -1) {
break;
}
bout.write(buff, 0, n);
}
fin.close();
byte[] link = bout.toByteArray();
// get the flags byte
byte flags = link[0x14];
// get the file attributes byte
final int file_atts_offset = 0x18;
byte file_atts = link[file_atts_offset];
byte is_dir_mask = (byte) 0x10;
if ((file_atts & is_dir_mask) > 0) {
is_dir = true;
} else {
is_dir = false;
}
// if the shell settings are present, skip them
final int shell_offset = 0x4c;
final byte has_shell_mask = (byte) 0x01;
int shell_len = 0;
if ((flags & has_shell_mask) > 0) {
// the plus 2 accounts for the length marker itself
shell_len = bytes2short(link, shell_offset) + 2;
}
// get to the file settings
int file_start = 0x4c + shell_len;
// get the local volume and local system values
final int basename_offset_offset = 0x10;
final int finalname_offset_offset = 0x18;
int basename_offset = link[file_start + basename_offset_offset]
+ file_start;
int finalname_offset = link[file_start + finalname_offset_offset]
+ file_start;
String basename = getNullDelimitedString(link, basename_offset);
String finalname = getNullDelimitedString(link, finalname_offset);
real_file = basename + finalname;
}
private static String getNullDelimitedString(byte[] bytes, int off) {
int len = 0;
// count bytes until the null character (0)
while (true) {
if (bytes[off + len] == 0) {
break;
}
len++;
}
return new String(bytes, off, len);
}
/*
* convert two bytes into a short note, this is little endian because it's
* for an Intel only OS.
*/
private static int bytes2short(byte[] bytes, int off) {
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
}
}
I've also worked( now have no time for that) on '.lnk' in Java. My code is here
It's little messy( some testing trash) but local and network parsing works good. Creating links is implemented too. Please test and send me patches.
Parsing example:
Shortcut scut = Shortcut.loadShortcut(new File("C:\\t.lnk"));
System.out.println(scut.toString());
Creating new link:
Shortcut scut = new Shortcut(new File("C:\\temp"));
OutputStream os = new FileOutputStream("C:\\t.lnk");
os.write(scut.getBytes());
os.flush();
os.close();
The solution of #Code Bling does not work for me for Files in the User directory.
For Example "C:/Users/Username/Filename.txt".
The reason for that is: in The_Windows_Shortcut_File_Format.pdf
that was mentioned by #Stefan Cordes on page 6 it says that only the first 2 bits are important for volumes info.
All other bits might be filled with random garbage when the first bit of volumes info is "0".
So if it comes to:
isLocal = (file_location_info_flag & 2) == 0;
then file_location_info_flag might be "3".
This file is still local but this line of code assigns false to isLocal.
So i suggest the following adjustment to #Code Bling's code:
isLocal = (file_location_info_flag & 1) == 1;
This short code is really usefull...
But two fixes are needed:
the isPotentialValidLink improved not to load file if name doesn't end with ".lnk"
public static boolean isPotentialValidLink(final File file) {
final int minimum_length = 0x64;
boolean isPotentiallyValid = false;
if (file.getName().toLowerCase().endsWith(".lnk"))
try (final InputStream fis = new FileInputStream(file)) {
isPotentiallyValid = file.isFile() && fis.available() >= minimum_length && isMagicPresent(getBytes(fis, 32));
} catch (Exception e) {
// forget it
}
return isPotentiallyValid;
}
the offset has to be computed with 32bits not only a byte...
final int finalname_offset = bytesToDword(link,file_start + finalname_offset_offset) + file_start;
final int basename_offset = bytesToDword(link,file_start + basename_offset_offset) + file_start;
I found other non-professional technique. getting my job done.
File file=new File("C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\TeamViewer.lnk");//shortcut link
FileInputStream stream=new FileInputStream(file);
DataInputStream st=new DataInputStream(stream);
byte[] bytes=new byte[(int)stream.getChannel().size()];
stream.read(bytes);
String data=new String(bytes);
int i1=data.indexOf("C:\\Program Files");
int i2=data.indexOf(".exe",i1);
System.out.println(data.substring(i1, i2+4));
The given code works well, but has a bug. A java byte is a signed value from -128 to 127. We want an unsigned value from 0 to 255 to get the correct results. Just change the bytes2short function as follows:
static int bytes2short(byte[] bytes, int off) {
int low = (bytes[off]<0 ? bytes[off]+256 : bytes[off]);
int high = (bytes[off+1]<0 ? bytes[off+1]+256 : bytes[off+1])<<8;
return 0 | low | high;
}

Categories

Resources