I'm trying to get an audio data from a AS library, from the documentation the function is like this:
protected function audioData():String
{
var ret:String="";
buffer.position = 0;
while (buffer.bytesAvailable > 0)
{
ret += buffer.readFloat().toString() + ";";
}
return ret;
}
In between my code and this library is another js that have this code:
audioData: function(){
return this.flashInterface().audioData().split(";");
},
From my code I access this like:
function getdata(){
var data = Recorder.audioData();
console.log("audioData: " + data);
}
However, I tried to output the returned value to Firebug, I get a very long comma-separated list of of floating point values, how can I get back the byte[] buffer? What I mean by buffer is similar to Java, since I will be accessing the buffer from Java via JSNI.
Here's the sample log output (actual log is very long):
-0.00030517578125,0.00006103515625,0.00115966796875,0.00146484375,-0.00091552734375,-0.000946044921875,-0.001983642578125,-0.003997802734375,-0.005126953125,-0.00360107421875,-0.0032958984375,-0.004119873046875,-0.00433349609375,-0.0023193359375,-0.0008544921875,-0.003448486328125,-0.00347900390625,-0.0054931640625,-0.0067138671875,-0.005279541015625,-0.006072998046875,
I can't re-compile the AS that creates the output, for now what I can do is to interface to the SWF component in javascript and accept its floating point and convert it back to byte array. There's just too many errors in my AS project in FDT 5 IDE that I already need to do the mockup of my application.
I really want to recompile the AS library to fit the need however right now I just want to use it as it is.
If you want to see the actual byte data in the byte array you can use the following :
protected function audioData():String
{
var ret:String="";
buffer.position = 0;
while (buffer.bytesAvailable > 0)
{
ret += buffer.readByte().toString();
}
return ret;
}
AFAIK the ByteArray class in as3 is already a byte array(as the name suggests :)) you can access it's data using the [] operator, as in byteArray[0] will give you the first byte.
You should be able to send the byte array to a url on your server with a post request with something like this:
var request:URLRequest = new URLRequest ("http://someurl");
var loader: URLLoader = new URLLoader();
request.contentType = "application/octet-stream";
request.method = URLRequestMethod.POST;
request.data = byteArray;
loader.load(_request);
Related
I have created a dummy model which returns the array input to it and deployed it on google-cloud ML-engine so I can check how it is decoding the audio sent in the request. I have been unable to send audio stored in a float array from an android app to the model in a way that it is correctly decoded. Though I have no problems when sending a request from Python.
I make the request as follows:
Audio is recorded into
short[] inputBuffer = new short[RECORDING_LENGTH];
Converted to a float array
float[] floatInputBuffer = new float[RECORDING_LENGTH];
for (int i = 0; i < RECORDING_LENGTH; ++i) {
floatInputBuffer[i] = (float) inputBuffer[i];
}
The form google cloud expects from predictions is (see data encoding section):
{"instances": [{"b64": "X5ad6u"}, {"b64": "IA9j4nx"}]}
So I put the audio into a map which mimics this.
public static String convertToBase64Bytes(float[] audio) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4 * audio.length);
for (int i = 0; i < audio.length; i++) {
float amplitude = audio[i];
byteBuffer.putFloat(amplitude);
}
byte[] data = byteBuffer.array();
String rtn = Base64.encodeToString(data, Base64.DEFAULT);
return rtn;
}
String audioByteString = convertToBase64Bytes(floatInputBuffer);
final ArrayList<HashMap<String, String>> requestList = new ArrayList<>();
HashMap<String, String> singleRequest = new HashMap<>();
singleRequest.put("b64", audioByteString);
requestList.add(singleRequest);
HashMap<String, ArrayList<HashMap<String, String>>> jsonRequest = new HashMap<>();
jsonRequest.put("instances", requestList);
I then call this function which sends the request and returns the result
public String sendRequest(HashMap<String, ArrayList<HashMap<String, String>>> jsonRequest) throws Exception {
HttpContent content = new JsonHttpContent(new JacksonFactory(), jsonRequest);
HttpRequest request = requestFactory.buildRequest(method.getHttpMethod(), url, content);
return request.execute().parseAsString();
}
Inspecting the output from the model. The shape of the array is correct, but the float values are not. They are usually pretty much zero (e to the power of -26 or so).
On the model side the serving input function of the model (created using a custom tensorflow Estimator) which processes the request is
def serving_input_fn():
feature_placeholders = {'b64': tf.placeholder(dtype=tf.string,
shape=[None],
name='source')}
audio_samples = tf.decode_raw(feature_placeholders['b64'], tf.float32)
inputs = {'inarray': audio_samples}
return tf.estimator.export.ServingInputReceiver(inputs, feature_placeholders)
I think I am passing the encoded float array as a base64 string incorrectly, as google cloud should automatically decode the base64 string due to the "b64" key and this worked correctly when sending requests from Python.
Does anyone know how to send a float array to a model on google cloud from android in a way that it will be correctly decoded?
It appears that this is a BytesOrder/endian-ness issue. From the ByteBuffer javadocs:
Primitive values are translated to (or from) sequences of bytes according to the buffer's current byte order, which may be retrieved and modified via the order methods. Specific byte orders are represented by instances of the ByteOrder class. The initial order of a byte buffer is always BIG_ENDIAN.
But TensorFlow's decode_raw defaults to little endian
little_endian: An optional bool. Defaults to True. Whether the input bytes are in little-endian order. Ignored for out_type values that are stored in a single byte like uint8.
The solution is to override one or the other defaults. Since ARM processors are natively big endian, perhaps stick with BigEndian in your Android code, and modify your TF code:
def serving_input_fn():
feature_placeholders = {
'audio_bytes': tf.placeholder(
dtype=tf.string,
shape=[None],
name='source'
)
}
audio_samples = tf.decode_raw(
feature_placeholders['audio_bytes'],
tf.float32,
little_endian=False
)
return tf.estimator.export.ServingInputReceiver(
feature_placeholders,
feature_placeholders
)
(I made a few other changes to the function as noted on a separate SO post)
I have a Java servlet which takes some data from an android app and returns a string data back to the android app using the following code.
response.getOutputStream().write(STRING_MESSAGE.getBytes());
The value I pass here is read from the android activity as:
InputStream is = con.getInputStream();
byte[] b = new byte[1024];
while(is.read(b) != -1) {
buffer.append(new String(b));
}
The value is then converted to String using:
String result = buffer.toString();
But after doing so, the result has some added unwanted characters (they appear as a '?' inside a diamond shape) appended to the original string I have passed from the servlet. How can I avoid this?
As nafas said, the encoding is probably the error.
Try to replace the writing on your os with this :
response.getOutputStream().write(STRING_MESSAGE.getBytes(Charset.forName("UTF-8")));
And you also have to apply the mod to the InputStream :
buffer.append(new String(b, Charset.forName("UTF-8")));
how can i convert the specific code written in Delphi to JAVA
try
LLine := TMemoryStream.Create;
IdTCPClient1.IOHandler.WriteLn('atext');
IdTCPClient1.IOHandler.ReadStream(LLine, -1);
LLine.Position := 0;
LLine.Read(intval, 4); //the server is sending memstream as integer + ajpeg image
Image1.Picture.Graphic.LoadFromStream(LLine);
finally
//free
end;
the above code works perfectly with Delphi , but now i want to create a java client too , but my own conversion is giving me error(java)
Image image = null ;
Socket socket = new Socket(someIP, myport);
My conversion is
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
String string = "atext\n";
byte buffer[] = string.getBytes();
out.write(buffer);
in.skip(4); // i don't want the integer
image = ImageIO.read(in);
the server is getting the text atext perfectly , but my java client is having a problem always image is showing a null value (i assigned a breakpoint and checked it );
The ImageIO.read(InputStream input) documentation says:
If no registered ImageReader claims to be able to read the resulting
stream, null is returned.
So the null value seems to be normal in this case. Have you checked that a matching ImageReader is registered? (For example by loading an existing, valid reference image file)
I am writing a firefox extension which needs to play a certain PCM stream. The samples are retrieved from a java module over LiveConnect:
Java code:
public class Synthesizer
{
...
public
float[] synthesizeFloats(int[] symbols)
{
// Some code to generate 32bit float PCM samples
...
return floatSamples;
}
...
}
Javascript code:
scream: function(samples)
{
var start = 0;
var elapsed = 0;
start = (new Date()).getTime();
var floatSamples = new Float32Array(samples);
elapsed = (new Date()).getTime() - start;
Firebug.Console.log("Converting array (2) - Elapsed time in ms " + elapsed);
var modulationProperties = this.defaultModulationProperties();
var audio = new Audio();
audio.mozSetup(1, modulationProperties.sampleFrequency);
var written = 0;
while (written < floatSamples.length) {
written += audio.mozWriteAudio(floatSamples.subarray(written));
}
},
// Synthesizer class was loaded and instantiaded over LiveConnect
var samples = synthesizer.synthesizeFloats(symbols);
scream(samples);
The above code works but very slowly. It appears that converting the java byte array into a Float32Array is quite expensive. The conversion is necessary as one can't pass a java byte array to the mozWriteAudio function.
My questions are:
Is there a way to do the conversion more efficiently?
Is there a way to make the java code return a Javascript Float32Array object instead a java object?
Is there a java implementation that allows playing PCM audio that may be used in a firefox extension? Using that java implementation from withing the javascript code will not necessitate the above conversion.
Any other ideas / directions would be appreciated.
I'm trying to get data from website which is encoded in UTF-8 and insert them into the database (MYSQL). Database is also encoded in UTF-8.
This is the method I use to download data from specific site.
public String download(String url) throws java.io.IOException {
java.io.InputStream s = null;
java.io.InputStreamReader r = null;
StringBuilder content = new StringBuilder();
try {
s = (java.io.InputStream)new URL(url).getContent();
r = new java.io.InputStreamReader(s, "UTF-8");
char[] buffer = new char[4*1024];
int n = 0;
while (n >= 0) {
n = r.read(buffer, 0, buffer.length);
if (n > 0) {
content.append(buffer, 0, n);
}
}
}
finally {
if (r != null) r.close();
if (s != null) s.close();
}
return content.toString();
}
If encoding is set to 'UTF-8' (r = new java.io.InputStreamReader(s, "UTF-8"); ) data inserted into database seems to look OK, but when I try to display it, I am getting something like this: C�te d'Ivoire, instead of Côte d'Ivoire.
All my websites are encoded in UTF-8.
Please help.
If encoding is set to 'windows-1252' (r = new java.io.InputStreamReader(s, "windows-1252"); ) everything works fine and I am getting Côte d'Ivoire on my website (), but in java this title looks like 'C?´te d'Ivoire' what breaks other things, such as for example links. What does it mean ?
I would consider using commons-io, they have a function doing what you want to do:link
That is replace your code with this:
public String download(String url) throws java.io.IOException {
java.io.InputStream s = null;
String content = null;
try {
s = (java.io.InputStream)new URL(url).getContent();
content = IOUtils.toString(s, "UTF-8")
}
finally {
if (s != null) s.close();
}
return content.toString();
}
if that nots doing start looking into if you can store it to file correctly to eliminate the possibility that your db isn't set up correctly.
Java
The problem seems to lie in the HttpServletResponse , if you have a servlet or jsp page. Make sure to set your HttpServletResponse encoding to UTF-8.
In a jsp page or in the doGet or doPost of a servlet, before any content is sent to the response, just do :
response.setCharacterEncoding("UTF-8");
PHP
In PHP, try to use the utf8-encode function after retrieving from the database.
Is your database encoding set to UTF-8 for both server, client, connection and have the tables been created with that encoding? Check 'show variables' and 'show create table <one-of-the-tables>'
If encoding is set to 'UTF-8' (r = new java.io.InputStreamReader(s, "UTF-8"); ) data inserted into database seems to look OK, but when I try to display it, I am getting something like this: C�te d'Ivoire, instead of Côte d'Ivoire.
Thus, the encoding during the display is wrong. How are you displaying it? As per the comments, it's a PHP page? If so, then you need to take two things into account:
Write them to HTTP response output using the same encoding, thus UTF-8.
Set content type to UTF-8 so that the webbrowser knows which encoding to use to display text.
As per the comments, you have apparently already done 2. Left behind 1, in PHP you need to install mb_string and set mbstring.http_output to UTF-8 as well. I have found this cheatsheet very useful.