I am thinking about building the code more efficiently. I am using Discord JDA and the Microsoft Azure speech service. Is it possible to recognize speech directly from bytes, not from a file? I mean, skipping writing bytes to a temporary file and then recognizing the file. Or maybe in some other, better way I can do it? The current method seems inappropriate to me.
My AudioReceiveHandler:
#Override
public void handleUserAudio(#NotNull UserAudio userAudio) {
User user = userAudio.getUser();
if (!BYTES.containsKey(user))
BYTES.put(user, new ArrayList<>());
ArrayList<byte[]> userBytes = BYTES.get(user);
userBytes.add(userAudio.getAudioData(1));
}
Converting speech to text:
private void read(ArrayList<byte[]> userBytes) {
int length = 0;
for (byte[] bytes : userBytes) {
length += bytes.length;
}
byte[] decodedData = new byte[length];
int i = 0;
for (byte[] bytes : userBytes) {
for (byte sampleByte : bytes) {
decodedData[i++] = sampleByte;
}
}
String filePath = "[...]/temp.wav";
try {
AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(decodedData),
new AudioFormat(48000f, 16, 2, true, true), decodedData.length),
AudioFileFormat.Type.WAVE,
new File(filePath));
} catch (IOException exception) {
exception.printStackTrace();
}
SpeechConfig speechConfig = SpeechConfig.fromSubscription("-", "-");
speechConfig.setSpeechRecognitionLanguage("pl-PL");
AudioConfig audioConfig = AudioConfig.fromWavFileInput(filePath);
SpeechRecognizer recognizer = new SpeechRecognizer(speechConfig, audioConfig);
Future<SpeechRecognitionResult> task = recognizer.recognizeOnceAsync();
try {
SpeechRecognitionResult result = task.get();
Logger.info("RECOGNIZED: " + result.getText());
} catch (Exception exception) {
exception.printStackTrace();
}
}
Related
i have arduino that send 2 int and the int was separate by " : "
for example my arduino send data = 12315: 15123
after i send that data using bluetooth, i receive the data in smartphone and i need that 2 value that i receive become int again
this is was my part code on my android
void beginListenForData()
{
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = mmInputStream.available();
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes, "US-ASCII");
readBufferPosition = 0;
handler.post(new Runnable()
{
public void run()
{
String[] tmp;
String lol,dam;
tmp = data.split(":");
try
{
lol = String.valueOf(crypt[0])+":"+String.valueOf(crypt[1]);
derajat.setText(lol);
}
catch (NumberFormatException nfe)
{
// bad data - set to sentinel
crypt[0] = Integer.MIN_VALUE;
crypt[1] = Integer.MIN_VALUE;
derajat.setText("none");
}
dam = tmp[0]+":"+tmp[1];
myLabel.setText(dam);
//derajat.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
}
catch (IOException ex)
{
stopWorker = true;
}
}
}
});
workerThread.start();
}
as you can see that after '\n' data will be process
first i split using data.split() and i get 2 value that stored in tmp
after that i parse that value to crypt[0] and crypt[1]
i set text to derajat to see my value
and i set text the result in myLabel too
i can see my value in myLabel but i cant convert it to int because i see nothing in label derajat
can somebody help me why i cant convert int after receiving that data ??
If the received data from your Arduino is in fact as you have specified:
"12315: 15123"
Then what is happening is that you are getting a NumberFormatException which you do catch but really have no way of knowing other than derajat will contain nothing (or "none")....which is exactly what you are experiencing.
The reason you would get a NumberFormatException is because there is a white-space directly after the colon (:) delimiter so when you try to carry out:
crypt[1] = Integer.parseInt(tmp[1]);
(tmp[1] actually holds " 15123") a NumberFormatException is thrown. The Integer.parseInt() method will not handle white-spaces within the numerical string. To remedy this trim your split strings, for example:
crypt[0] = Integer.parseInt(tmp[0].trim());
crypt[1] = Integer.parseInt(tmp[1].trim());
or split with:
tmp = data.split(": ");
Alright, so I am writing a small program that should have taken 10 minutes to complete however I am running into unforeseen problems.
The program should take in some old files I had in a vault program on my old phone, they are basically Jpg files but with an added "obscured" text to the front of the file.
So below is my code logic
get a folder input for the files,
create an arraylist containing each actual file.
call ConvertFiles to convert the file to a string,
delete the first 8 characters using substring and save that temp file to another arraylist containing the strings.
decode that string as base64 and input that into a bytearrayinputstream and save that to a bufferedimage.
This is where the problem occurs. I have content all the way up to the ImageIO.read(bis), so when it tries to write to a new file it throws the image == null
from the ImageTypeSpecifier. I have tried multiple ways of decoding and encoding the string, but any help is wanted and if any more information is needed I will provide it!
public class ImageConvert {
private File folder;
private ArrayList<File> files;
private ArrayList<String> stringFiles = new ArrayList<>();
private ArrayList<BufferedImage> bfImages = new ArrayList<>();
boolean isRunning = true;
Scanner scanner = new Scanner(System.in);
String folderPath;
public static void main(String[] args) {
ImageConvert mc = new ImageConvert();
mc.mainCode();
}
public void mainCode(){
System.out.println("Please enter the folder path: ");
folderPath = scanner.nextLine();
folder = new File(folderPath);
//System.out.println("folderpath: " + folder);
files = new ArrayList<File>(Arrays.asList(folder.listFiles()));
convertFiles();
}
public void convertFiles(){
for(int i = 0; i < files.size(); i++){
try {
String temp = FileUtils.readFileToString(files.get(i));
//System.out.println("String " + i + " : " + temp);
stringFiles.add(temp.substring(8));
} catch (IOException ex) {
Logger.getLogger(ImageConvert.class.getName()).log(Level.SEVERE,
null, ex);
}
}
//System.out.println("Converted string 1: " + stringFiles.get(0));
for(int j = 0; j < stringFiles.size(); j++){
BufferedImage image = null;
byte[] imageByte;
try {
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(stringFiles.get(j));
System.out.println(imageByte.toString());
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
bfImages.add(image);
} catch (IOException ex) {
Logger.getLogger(ImageConvert.class.getName()).log(Level.SEVERE,
null, ex);
}
}
System.out.println("Image 1: " + bfImages.get(0));
for(int k = 0; k < bfImages.size(); k++){
try {
ImageIO.write(bfImages.get(k), "jpg",
new File(folderPath + "/" + k + ".jpg"));
} catch (IOException ex) {
Logger.getLogger(ImageConvert.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
This is an example of my files:
The following example uses the file you included with your question. You don't need to do any decoding, just read the file into memory, store the 8 byte String and then write the remaining bytes to a jpg from an 8 byte offset.
Just adapt the method below to work with your: "folder input for files". You don't need an ArrayList containing each actual jpg file.
public void convertFiles() {
File imgFile;
byte[] bytes;
FileOutputStream fos;
String temp;
for (int i = 0; i < files.size(); i++) {
temp = "";
try {
// 'read' method can be found below
bytes = read(files.get(i));
// read the 8 byte string from the beginning of the file
for(int j = 0; j < 8; j++) {
temp += (char) bytes[j];
}
imgFile = new File("img.jpg");
// points to './img.jpg'
fos = new FileOutputStream(imgFile);
// write from offset 8 to end of 'bytes'
fos.write(bytes, 8, bytes.length - 8);
fos.close();
} catch (FileNotFoundException e) {
// Logger stuff
} catch (IOException ex) {
// Logger stuff
}
System.out.println("[temp]:> " + temp);
}
}
read(File file) method adapted from a community wiki answer to File to byte[] in Java
public byte[] read(File file) throws IOException {
ByteArrayOutputStream ous = null;
InputStream ios = null;
try {
byte[] buffer = new byte[4096];
ous = new ByteArrayOutputStream();
ios = new FileInputStream(file);
int read = 0;
while ((read = ios.read(buffer)) != -1) {
ous.write(buffer, 0, read);
}
} finally {
try {
if (ous != null)
ous.close();
} catch (IOException e) {
}
try {
if (ios != null)
ios.close();
} catch (IOException e) {
}
}
return ous.toByteArray();
}
Output:
[temp]:> obscured
Image File:
I have tried make a app in Android that show the hardware specifications of a device, example:
Processor: Quad Core 1.2 Ghz
1 GB Memory RAM
8 GB Storage
Android Version 4.4
Would someone help me to find a library that allows me do it?
You can use this code
Log.i("ManuFacturer :", Build.MANUFACTURER);
Log.i("Board : ", Build.BOARD);
Log.i("Display : ", Build.DISPLAY);
More info can be found at from http://developer.android.com/reference/android/os/Build.html
I do not know a library that can extract specific hardware specifications, however, the Facebook Device-Year-Class library can classify devices into 'years' based on Hardware specs:
Github: Device-Year-Class
Additionally, you can look through their code to detect how they get info such as the Max Freq KHz:
public static int getCPUMaxFreqKHz() {
int maxFreq = DEVICEINFO_UNKNOWN;
try {
for (int i = 0; i < getNumberOfCPUCores(); i++) {
String filename =
"/sys/devices/system/cpu/cpu" + i + "/cpufreq/cpuinfo_max_freq";
File cpuInfoMaxFreqFile = new File(filename);
if (cpuInfoMaxFreqFile.exists()) {
byte[] buffer = new byte[128];
FileInputStream stream = new FileInputStream(cpuInfoMaxFreqFile);
try {
stream.read(buffer);
int endIndex = 0;
//Trim the first number out of the byte buffer.
while (Character.isDigit(buffer[endIndex]) && endIndex < buffer.length) {
endIndex++;
}
String str = new String(buffer, 0, endIndex);
Integer freqBound = Integer.parseInt(str);
if (freqBound > maxFreq) {
maxFreq = freqBound;
}
} catch (NumberFormatException e) {
//Fall through and use /proc/cpuinfo.
} finally {
stream.close();
}
}
}
if (maxFreq == DEVICEINFO_UNKNOWN) {
FileInputStream stream = new FileInputStream("/proc/cpuinfo");
try {
int freqBound = parseFileForValue("cpu MHz", stream);
freqBound *= 1000; //MHz -> kHz
if (freqBound > maxFreq) maxFreq = freqBound;
} finally {
stream.close();
}
}
} catch (IOException e) {
maxFreq = DEVICEINFO_UNKNOWN; //Fall through and return unknown.
}
return maxFreq;
}
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?
My android application is getting data from Polar Heart Rate Monitor through Bluetooth connection.
My problem is that I am getting such a string:
��������������������������������������������������
My code for getting the data:
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
stopWorker = false;
readBufferPosition = 0;
readBuffer = new byte[1024];
workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = mmInputStream.available();
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
mmInputStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition];
// System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes, "ASCII");
readBufferPosition = 0;
handler.post(new Runnable()
{
public void run()
{
pulsText.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
}
catch (IOException ex)
{
stopWorker = true;
}
}
}
});
workerThread.start();
I tried to change this line in few ways but I am still getting incorrect data:
final String data = new String(encodedBytes, "ASCII");
How can I solve this issue ?
Please help !!!
The sensor doesn't give you printable strings (like e.g. NMEA does) but binary data that you need to parse. You could look into the MyTracks Polar Sensor data parser for inspiration.
You are using available and read incorrectly (but the way you use you could have luck most of the time).
The Units of Measurement (based on Raspberry Pi Challenge at JavaOne) "Heart of Glass" project shows, how this can be parsed into a typesafe Heartbeat Unit for display or transfer to other systems.