How to normalize mixed WAV files - java

I am trying to mix two WAV files.
The WAV files are available as byte arrays and I am using below code to mix the two.
byte[] byte1 , byte[] byte2
// 44 is header of wav file
for( int i = 44 ; i < byte1.length ; i++){
byte1[i] = byte1[i] + byte2[i];
}
The above code mostly works. But when the result is more than maximum wave (16 bit audio file), it has noise. How can I normalize mixed sound?

First of all, if, indeed, your audio is 16 bits, adding it byte-by-byte won't work. Other people commented on this. You can see my answer here for how to handle this problem.
using Android's AudioTrack to combine bytes of sound samples produces noise
Secondly, to "normalize" it, you'll have to find the peak first, and then scale all results to that value. That means two loops: one to find the "peak" and one to add the values, scaling to the new peak. Something like this:
//this is the raw audio data -- no header
short[] audioData1 , short[] audioData2
//find the max:
float max = 0;
for( int i = 0 ; i < audioData1.length ; i++) {
if( Math.abs( audioData1[i] + audioData2[i] ) > max )
max = Math.abs( audioData1[i] + audioData2[i] );
}
//now find the result, with scaling:
for( int i = 0 ; i < audioData1.length ; i++) {
audioData1[i] = Math.Round(Short.MAX_VALUE * ( audioData1[i] + audioData2[i] ) / max) ;
}
//normalized result in audioData1

short[] audioData1 = null;
short[] audioData2 = null;
int n = 0;
try {
DataInputStream in1;
in1 = new DataInputStream(new FileInputStream("v1.wav"));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
while ((n = in1.read()) != -1) {
bos.write(n);
}
} catch (IOException e) {
e.printStackTrace();
}
ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
bb.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
audioData1 = new short[sb.capacity()];
for (int i = 0; i < sb.capacity(); i++) {
audioData1[i] = sb.get(i);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
DataInputStream in1;
in1 = new DataInputStream(new FileInputStream("v2.wav"));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
while ((n = in1.read()) != -1) {
bos.write(n);
}
} catch (IOException e) {
e.printStackTrace();
}
ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
bb.order(ByteOrder.LITTLE_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
audioData2= new short[sb.capacity()];
sb.get(audioData2);
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
// find the max:
float max = 0;
for (int i = 22; i < audioData1.length; i++) {
if (Math.abs(audioData1[i] + audioData2[i]) > max)
max = Math.abs(audioData1[i] + audioData2[i]);
}
System.out.println("" + (Short.MAX_VALUE - max));
int a, b, c;
// now find the result, with scaling:
for (int i = 22; i < audioData1.length; i++) {
a = audioData1[i];
b = audioData2[i];
c = Math.round(Short.MAX_VALUE * (audioData1[i] + audioData2[i])
/ max);
if (c > Short.MAX_VALUE)
c = Short.MAX_VALUE;
if (c < Short.MIN_VALUE)
c = Short.MIN_VALUE;
audioData1[i] = (short) c;
}
// to turn shorts back to bytes.
byte[] end = new byte[audioData1.length * 2];
ByteBuffer.wrap(end).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(audioData1);
try {
OutputStream out = new FileOutputStream("mixer.wav");
for (int i = 0; i < end.length; i++) {
out.write(end[i]);
out.flush();
}
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this works, thanks all for answers

short[] audioData1 = null;
short[] audioData2 = null;
int n = 0;
DataInputStream in1;
try {
in1 = new DataInputStream(new FileInputStream("audio1.wav"));
audioData1 = new short[in1.available() / 2];
ShortBuffer b1 = ShortBuffer.wrap(audioData1);
try {
while (true) {
n = in1.readShort();
b1.put((short) n);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
DataInputStream in2;
try {
in2 = new DataInputStream(new FileInputStream("audio2.wav"));
audioData2 = new short[in2.available() / 2];
ShortBuffer b2 = ShortBuffer.wrap(audioData2);
try {
while (true) {
n = in2.readShort();
b2.put((short) n);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
// find the max:
float max = 0;
for (int i = 44; i < audioData1.length; i++) {
if (Math.abs(audioData1[i] + audioData2[i]) > max)
max = Math.abs(audioData1[i] + audioData2[i]);
}
// now find the result, with scaling:
for (int i = 44; i < audioData1.length; i++) {
audioData1[i] = (short) Math.round(Short.MAX_VALUE
* (audioData1[i] + audioData2[i]) / max);
}
DataOutputStream out;
try {
out = new DataOutputStream(new FileOutputStream("mix.wav"));
for (int i = 0; i < audioData1.length; i++) {
out.writeShort(audioData1[i]);
out.flush();
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
now it is in short, it won't work because value max is 32768 (max short) and nothing changed

Related

How to create an audio wave in JavaFX?

I would like to get an Audio wave plot using Chart Area in JavaFX. Unfortunately, I am not clear how to do, what are the values ​​to be extracted from the sound to assign to x-axis and y-axis?
I tried to read other posts, but I found nothing on javafx.
You can help me?
Sample Image:
Below is the code that extract the waveform .
I'm pulling out the right parameters for my scope?
How can I use it to print the graph with JavaFX?
public class SimpleWaveformExtractor implements WaveformExtractor {
private static final int DEFAULT_BUFFER_SIZE = 32768;
#Override
public double[] extract(File inputFile) {
AudioInputStream in = null;
try {
in = AudioSystem.getAudioInputStream(inputFile);
} catch (Exception e) {
System.out.println("Cannot read audio file");
return new double[0];
}
AudioFormat format = in.getFormat();
byte[] audioBytes = readBytes(in);
int[] result = null;
if (format.getSampleSizeInBits() == 16) {
int samplesLength = audioBytes.length / 2;
result = new int[samplesLength];
if (format.isBigEndian()) {
for (int i = 0; i < samplesLength; ++i) {
byte MSB = audioBytes[i * 2];
byte LSB = audioBytes[i * 2 + 1];
result[i] = MSB << 8 | (255 & LSB);
}
} else {
for (int i = 0; i < samplesLength; i += 2) {
byte LSB = audioBytes[i * 2];
byte MSB = audioBytes[i * 2 + 1];
result[i / 2] = MSB << 8 | (255 & LSB);
}
}
} else {
int samplesLength = audioBytes.length;
result = new int[samplesLength];
if (format.getEncoding().toString().startsWith("PCM_SIGN")) {
for (int i = 0; i < samplesLength; ++i) {
result[i] = audioBytes[i];
}
} else {
for (int i = 0; i < samplesLength; ++i) {
result[i] = audioBytes[i] - 128;
}
}
}
return ArraysHelper.normalize(result);
}
private byte[] readBytes(AudioInputStream in) {
byte[] result = new byte[0];
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
try {
int bytesRead = 0;
do {
bytesRead = in.read(buffer);
result = ArrayUtils.addAll(result, buffer);
} while (bytesRead != -1);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
this is the interface:
public interface WaveformExtractor {
double[] extract(File in);
}
This is the code that return the array of double:
private double[] extractWaveform(File file) throws IOException, UnsupportedAudioFileException {
return new WavFileExtractor().extract(file);
}

Why doesn't a socket send the last message unless there is a delay before it?

Alright so I am looking at this piece of code that is supposed to get an array of bytes which represents an image and send it piece by piece to a server. The server needs to be told when the image transmission is done, this ending message is "CLOSE". Everything works fine but unless I uncomment Thread.sleep the end message isn't sent. Also the delay needs to be quite big for some reason, 100 ms for example doesn't work. If anyone could provide an explanation for this behaviour I would be grateful since I don't have a very good understanding of java.
private class NetTask extends AsyncTask<Void, Void, Void>
{
private String ip;
private byte[] to_send;
public NetTask(String ip, byte[] to_send)
{
this.ip = ip;
this.to_send = to_send;
}
#Override
protected Void doInBackground(Void...params)
{
try {
Log.i(dTag, "" + to_send.length);
Socket sck = new Socket(ip, 1234);
DataOutputStream dOut = new DataOutputStream(sck.getOutputStream());
dOut.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(to_send.length).array());
Log.d(dTag, "" + to_send.length);
int x = 500;
int len = to_send.length;
for (int i = 0; i < len - x + 1; i += x)
dOut.write(Arrays.copyOfRange(to_send, i, i + x));
if (len % x != 0)
dOut.write(Arrays.copyOfRange(to_send, len - len % x, len));
/*try {
Thread.sleep(1000);
}
catch (Exception ex) {
Log.d(dTag, "thread sleep error");
}*/
dOut.write("CLOSE".getBytes());
dOut.flush();
dOut.close();
sck.close();
}
catch (IOException ex) {
Log.d(dTag, ex.getMessage());
}
return null;
}
}
The server is in c#, here is the code:
while (ok)
{
sck.Listen(1000);
Socket accepted = sck.Accept();
buffer = new byte[accepted.SendBufferSize];
int bytesRead = -1;
bool reading = true;
int im_size = -1;
int index = 0;
byte[] image = null;
while (reading)
{
bytesRead = accepted.Receive(buffer);
if (bytesRead == 5)
Console.WriteLine(bytesRead);
string strData = "YADA";
byte[] formatted = new byte[bytesRead];
if (bytesRead == 5)
{
for (int i = 0; i < bytesRead; i++)
{
formatted[i] = buffer[i];
}
strData = Encoding.ASCII.GetString(formatted);
}
if (strData == "CLOSE")
{
Console.WriteLine("GOT CLOSE MESSAGE");
Image im = Image.FromStream(new MemoryStream(image));
im.Save(#"D:\im1.bmp");
}
else
{
if (im_size == -1)
{
im_size = BitConverter.ToInt32(buffer, 0);
image = new byte[im_size];
Console.WriteLine(im_size);
}
else
{
for (int i = 0; i < bytesRead && index < im_size; i++)
{
image[index++] = buffer[i];
}
}
}
}
accepted.Close();
}

java socket takes too much cpu% and virtual memory

I have developed a java socket, but it takes too many cpu and virtual memory usages.
Can you tell me what is the problem in my code?
private void listen() {
try {
serverSocket = new ServerSocket(port);
System.out.println("Server socket listening on port: " + port);
System.out.println("Waiting for connections...");
while(true) {
// accept the connection
Socket socket = serverSocket.accept();
socket.setSoTimeout(30000);
System.out.println("Got connection");
// start processing the connection
Thread connectionManager = new Thread(new Elevator(socket, socket.getInputStream()));//new Thread(new ConnectionManager(socket, odometer));
connectionManager.start();
}
} catch (IOException exc) {
System.out.println(Listener.class.getName() + ": " + exc.getMessage());
}
}
in Elevator class I have this:
public class Elevator implements Runnable
{
private String imei;
private Socket socket;
private InputStream is;
private PrintWriter out;
private OutputStream ds;
private int packetL;
private long timestamp;
dbElevatorManipulate dbElevator;
private String[] allCards = null;
private String[] insCards = null;
private String[] upddelCards = null;
private String[] config = null;
public Elevator(Socket socket, InputStream is) {
this.socket = socket;
this.is = is;
initializeOutputStream(socket);
}
private void initializeOutputStream(Socket socket) {
try {
ds = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
out = new PrintWriter(ds, true);
}
#Override
public void run(){
int codecL = 1;
int imeiL = 16;
String codecID = "";
String imeiFromBoard = "";
byte[] codecBuffer = new byte[codecL];
byte[] imeiBuffer = new byte[imeiL];
try{
// Read codec ID.
is.read(codecBuffer, 0, codecL);
codecID = byteToString(codecBuffer);
//System.out.println("Codec ID : " + codecID);
// Read imei.
is.read(imeiBuffer, 0, imeiL);
imeiFromBoard = byteToString(imeiBuffer);
if (codecID.equals("2")) {
byte[] crc = new byte[2];
is.read(crc);
byte[] cnnpacket = new byte[codecL + imeiL];
cnnpacket[0] = codecBuffer[0];
for (int i = 1; i < cnnpacket.length; i++) {
cnnpacket[i] = imeiBuffer[i-1];
}
if(DataLayer.checksum(cnnpacket, crc))
{
try {
ds.write(1);
ds.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
try {
ds.close();
is.close();
dbElevator.disconnect();
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return;
}
}
}
catch(Exception ex)
{
System.out.println("Error: " + ex.getMessage());
}
imeiFromBoard = imeiFromBoard.substring(1, imeiFromBoard.length());
imei = imeiFromBoard;
System.out.println("got connection with imei:" + imei);
dbElevator = new dbElevatorManipulate(imei);
dbElevator.connect();
try{
while(true){
byte[] packet = new byte[1024];
int i = 0;
int byteread = is.read(packet);
if(byteread == -1) continue;
int cmdL = 1;
int dataLen = 2;
byte[] cmdBuffer = new byte[cmdL];
byte[] lengthBuffer = new byte[dataLen];
// Read and Print cmd.
cmdBuffer[0] = packet[0];
if(cmdBuffer[0] > 9 || cmdBuffer[0] < 0){
continue;
}
// Read and Print data length.
lengthBuffer[0] = packet[1];
lengthBuffer[1] = packet[2];
packetL = Integer.parseInt(DataLayer.byteToString(lengthBuffer));
// Reading a printing the packet .
byte[] packetBuffer = new byte[packetL];
int pcnt = 3;
while(packetL-- > 0)
{
packetBuffer[pcnt - 3] = packet[pcnt];
pcnt++;
}
String packetData = DataLayer.byteToString(packetBuffer);
// Reading and printing crc
int crcL = 2;
byte[] crcBuffer = new byte[crcL];
crcBuffer[0] = packet[pcnt];
crcBuffer[1] = packet[pcnt + 1];
if (DataLayer.checksum(packetBuffer, crcBuffer)) {
System.out.println("Packet: OK");
switch(cmdBuffer[0])
{
case 0:
int nrOfPackets = dbElevator.getNrOfTotalPackets();
int nCrc = DataLayer.crc16(new byte[] {(byte)nrOfPackets});
byte[] sendPacket = new byte[3];
sendPacket[0] = (byte)nrOfPackets;
sendPacket[1] = (byte)((nCrc >> 8) & 0xff); // hight byte of crc
sendPacket[2] = (byte)(nCrc & 0xff); // low byte of crc
ds.write(sendPacket);
ds.flush();
allCards = dbElevator.getTotalCards().split(",");
break;
case 1:
int PacketNo = Integer.parseInt(packetData);
if(allCards != null)
sendAllPacket(PacketNo);
break;
case 2:
int nrOfUpdPackets = dbElevator.getUpdDelCardsNo();
int updCrc = DataLayer.crc16(new byte[] {(byte)nrOfUpdPackets});
byte[] sendUpdPacket = new byte[3];
sendUpdPacket[0] = (byte)nrOfUpdPackets;
sendUpdPacket[1] = (byte)((updCrc >> 8) & 0xff); // hight byte of crc
sendUpdPacket[2] = (byte)(updCrc & 0xff); // low byte of crc
ds.write(sendUpdPacket);
ds.flush();
upddelCards = dbElevator.getUpdDelCards().split(",");
break;
case 3:
int updPacketNo = Integer.parseInt(packetData);
sendUpdDelPacket(updPacketNo);
break;
case 4:
int nrOfInsPackets = dbElevator.getInsertedCardsNo();
int insCrc = DataLayer.crc16(new byte[] {(byte)nrOfInsPackets});
byte[] sendInsPacket = new byte[3];
sendInsPacket[0] = (byte)nrOfInsPackets;
sendInsPacket[1] = (byte)((insCrc >> 8) & 0xff); // hight byte of crc
sendInsPacket[2] = (byte)(insCrc & 0xff); // low byte of crc
ds.write(sendInsPacket);
ds.flush();
insCards = dbElevator.getInsertedCards().split(",");
break;
case 5:
int insPacket = Integer.parseInt(packetData);
sendInsPacket(insPacket);
break;
case 6:
insertCheckInIntoDB(packetBuffer);
break;
case 7:
config = dbElevator.getConfig().split(",");
sendConfig(config);
break;
case 8: //log cards and close connection
try {
if(insCards != null && insCards.length > 2)
{
dbElevator.resetActionForIns(insCards);
dbElevator.LogSent_insCards(insCards);
}
if(upddelCards != null && upddelCards.length > 2)
{
dbElevator.resetActionForUpd(upddelCards);
dbElevator.LogSent_updCards(upddelCards);
}
if(allCards != null && allCards.length > 2)
{
dbElevator.resetActionForAll(allCards);
dbElevator.LogSent_allCards(allCards);
}
if(config != null && config.length > 0)
{
dbElevator.ConfigSent();
}
ds.close();
is.close();
dbElevator.disconnect();
System.out.println("database disconnected");
socket.close();
System.out.println("socket closed.");
return;
} catch (IOException e) {
e.printStackTrace();
}
break;
case 9:
int sendConfig = dbElevator.getSendConfig();
int sendConfigCRC = DataLayer.crc16(new byte[] {(byte)sendConfig});
byte[] sendConfigConfirm = new byte[3];
sendConfigConfirm[0] = (byte)sendConfig;
sendConfigConfirm[1] = (byte)((sendConfigCRC >> 8) & 0xff);
sendConfigConfirm[2] = (byte)(sendConfigCRC & 0xff);
ds.write(sendConfigConfirm);
ds.flush();
break;
}
}else{
//System.out.println("Packet: error");
ds.write(0x00);
ds.flush();
}
}
}catch(IOException e){
e.printStackTrace();
}
finally{
try {
ds.close();
System.out.println("ds closed.");
is.close();
System.out.println("is closed.");
dbElevator.disconnect();
System.out.println("db disconnected.");
socket.close();
System.out.println("socket closed.");
//break;
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private void sendConfig(String[] config) throws IOException {
byte[] packet = new byte[16*3];
for(int c = 0, i = 0; c<32; c++)
{
if(c<16){
int temp = Integer.parseInt(config[c],2);
packet[i++] = (byte)((temp >> 8) & 0xff);
packet[i++] = (byte)(temp & 0xff);
}
else
{
packet[i++] = (byte)(Integer.parseInt(config[c]) & 0xff);
}
}
int crc = DataLayer.crc16(packet);
byte[] txPacket = new byte[3*16 + 2];
for(int i = 0; i<16*3; i++)
{
txPacket[i] = packet[i];
}
txPacket[16*3] = (byte)((crc >> 8) & 0xff);
txPacket[16*3 + 1] = (byte)((crc) & 0xff);
ds.write(txPacket);
ds.flush();
}
private void insertCheckInIntoDB(byte[] packetData){
String values = "";
try{
for(int i = 0; i<packetData.length; i+=8)
{
byte[] siteCode = new byte[1];
siteCode[0] = packetData[i];
byte[] siteNo = new byte[2];
siteNo[0] = packetData[i + 1];
siteNo[1] = packetData[i + 2];
byte[] Floor = new byte[1];
Floor[0] = (byte)(packetData[i + 3] >> 4 & 0xf);
byte[] Valide = new byte[1];
Valide[0] = (byte)(packetData[i + 3] & 0xf);
byte[] timestamp = new byte[4];
timestamp[0] = packetData[i + 4];
timestamp[1] = packetData[i + 5];
timestamp[2] = packetData[i + 6];
timestamp[3] = packetData[i + 7];
if(Long.parseLong(DataLayer.byteToString(timestamp)) < 1410000000)
{
continue;
}
values += "(" + imei + ",";
values += DataLayer.byteToString(siteCode) + ",";
values += DataLayer.byteToString(siteNo) + ",";
values += DataLayer.byteToString(Floor) + ",";
values += DataLayer.byteToString(Valide) + ",";
values += DataLayer.byteToString(timestamp) + "),";
}
values = values.substring(0, values.length()-1);
if(dbElevator.insertCheckIn(values))
{
ds.write(1);
ds.flush();
return;
}
else
{
try {
ds.write(0);
ds.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
catch(Exception ex){
try {
ds.write(0);
ds.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void sendUpdDelPacket(int updPacketNo) throws IOException {
byte[] packet = new byte[38*6];
for(int i = 0, c = 38*4*updPacketNo; i<38*6; i+=6, c+=4)
{
if(c + 3 < upddelCards.length)
{
packet[i] = (byte)Integer.parseInt(upddelCards[c]);
//System.out.println(upddelCards[c+1]);
packet[i+1] = (byte)(Integer.parseInt(upddelCards[c+1]) >> 8 & 0xff);
packet[i+2] = (byte)(Integer.parseInt(upddelCards[c+1]) & 0xff);
packet[i+3] = (byte)(Integer.parseInt(upddelCards[c+2], 2) >> 8 & 0xff);
packet[i+4] = (byte)(Integer.parseInt(upddelCards[c+2], 2) & 0xff);
packet[i + 5] = (byte)Integer.parseInt(upddelCards[c + 3]);
}
else
{
packet[i] = 0;
packet[i+1] = 0;
packet[i+2] = 0;
packet[i+3] = 0;
packet[i+4] = 0;
packet[i+5] = 0;
}
}
int crc = DataLayer.crc16(packet);
byte[] txPacket = new byte[38*6 + 2];
for(int i = 0; i<38*6; i++)
{
txPacket[i] = packet[i];
}
txPacket[38*6] = (byte)((crc >> 8) & 0xff);
txPacket[38*6 + 1] = (byte)((crc) & 0xff);
ds.write(txPacket);
ds.flush();
}
private void sendInsPacket(int packetNo) throws IOException {
byte[] packet = new byte[46*5];
for(int i = 0, c = 46*3*packetNo; i< 46*5; i+=5, c+=3)
{
if(c + 2 < insCards.length)
{
packet[i] = (byte)Integer.parseInt(insCards[c]);
packet[i+1] = (byte)(Integer.parseInt(insCards[c+1]) >> 8 & 0xff);
packet[i+2] = (byte)(Integer.parseInt(insCards[c+1]) & 0xff);
packet[i+3] = (byte)(Integer.parseInt(insCards[c+2], 2) >> 8 & 0xff);
packet[i+4] = (byte)(Integer.parseInt(insCards[c+2], 2) & 0xff);
}
else
{
packet[i] = 0;
packet[i+1] = 0;
packet[i+2] = 0;
packet[i+3] = 0;
packet[i+4] = 0;
}
}
int crc = DataLayer.crc16(packet);
byte[] txPacket = new byte[46*5 + 2];
for(int i = 0; i<46*5; i++)
{
txPacket[i] = packet[i];
}
txPacket[46*5] = (byte)((crc >> 8) & 0xff);
txPacket[46*5 + 1] = (byte)((crc) & 0xff);
ds.write(txPacket);
ds.flush();
}
private void sendAllPacket(int packetNo) throws IOException {
byte[] packet = new byte[46*5];
for(int i = 0, c = 46*3*packetNo; i< 46*5; i+=5, c+=3)
{
if(c + 2 < allCards.length)
{
packet[i] = (byte)Integer.parseInt(allCards[c]);
packet[i+1] = (byte)(Integer.parseInt(allCards[c+1]) >> 8 & 0xff);
packet[i+2] = (byte)(Integer.parseInt(allCards[c+1]) & 0xff);
packet[i+3] = (byte)(Integer.parseInt(allCards[c+2], 2) >> 8 & 0xff);
packet[i+4] = (byte)(Integer.parseInt(allCards[c+2], 2) & 0xff);
}
else
{
packet[i] = 0;
packet[i+1] = 0;
packet[i+2] = 0;
packet[i+3] = 0;
packet[i+4] = 0;
}
}
int crc = DataLayer.crc16(packet);
byte[] txPacket = new byte[46*5 + 2];
for(int i = 0; i<46*5; i++)
{
txPacket[i] = packet[i];
}
txPacket[46*5] = (byte)((crc >> 8) & 0xff);
txPacket[46*5 + 1] = (byte)((crc) & 0xff);
ds.write(txPacket);
ds.flush();
}
private static String byteToString(byte[] buffer) {
StringBuilder s = new StringBuilder();
for (byte b : buffer) {
s.append((char) b);
}
return s.toString();
}
What can I do about this problem ?
Thanks in advance.
You appear to be doing a lot of small reads directly on a socket's input stream. You should get better performance if you wrap the input stream with a buffered input stream.
The use of buffered streams is discussed in the Oracle Java Tutorial.
The output side looks a bit better. You are assembling packets, and writing them in large(er) write calls. However, I'm still suspicious of that ... and the possibility that some of the flush calls are unnecessary.
As EJP points out, your I/O code is fragile because you don't take account of the possibility that the "other end" has closed the socket. This will cause read and equivalent calls to return without reading anything.
Note that the read methods return the number of bytes (or characters) that they have read, or -1 if they detect "end of stream". Your code is completely ignoring the return value.
It is possible that this is the cause of your performance problems; e.g. if a thread is repeatedly calling read on a socket that is in "end of stream" state.
Another possible problem with your code is that your listen method is creating a brand new Thread each time an accept() call succeeds.
If you have lots of clients connecting, there will be lots of threads, and this results in lots of resource usage.
If clients don't disconnect and/or the server doesn't notice that they have disconnected, then the resources will leak, and your server will never give them back.
If you are leaking threads, and those threads are sitting idle, then they are wasting memory. (A thread stack is typically 1Mb or so.) If they are not idle (e.g. because of a bug in your read code ... like not dealing with the "end of stream" condition properly) then you will be wasting CPU too.
#chanjaster suggested using an executor with a fixed sized thread pool. This might help in a couple of respects:
It prevents the application using an unbounded number of threads.
It recycles the threads after they are no longer active ... which reduces overheads.
However, if you have a resource leakage problem, a thread pool won't cure this. Indeed, what will probably happen is that new connections just freeze. (They go into the task queue waiting for a worker thread to pick them up. And that never happens.)

Java output values over time

I have an audio file that I am converting into a byte array, but then you cannot tell when that byte value is actually played in the song. So I am trying to stretch it out over the length of the song.
So while the song is playing, it outputs the byte value. How is this possible?
Here is my code so far:
public class Main {
private static final String FILENAME = "assets/pf.wav";
private static double[] endResult = null;
public static void convert() throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(FILENAME));
int read;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
endResult = calculateFFT(audioBytes);
}
public static double[] calculateFFT(byte[] signal)
{
final int mNumberOfFFTPoints =1024;
double mMaxFFTSample;
double temp;
Complex[] y;
Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
double[] absSignal = new double[mNumberOfFFTPoints/2];
for(int i = 0; i < mNumberOfFFTPoints; i++){
temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
complexSignal[i] = new Complex(temp,0.0);
}
y = FFT.fft(complexSignal);
mMaxFFTSample = 0.0;
int mPeakPos = 0;
for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
{
absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
if(absSignal[i] > mMaxFFTSample)
{
mMaxFFTSample = absSignal[i];
mPeakPos = i;
}
}
return absSignal;
}
public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
File file = new File(FILENAME);
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);
AudioFormat format = audioInputStream.getFormat();
long frames = audioInputStream.getFrameLength();
final double durationInSeconds = (frames+0.0) / format.getFrameRate();
try {
convert();
for(int i = 0; i < endResult.length; i++) {
System.out.println(endResult[i]);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
How can I print out the value of the byte array (endResult[i]) over time and not immediately?
Whenever you print out a value, do:
Thread.sleep(100);
To wait 100 milliseconds (0.1 seconds) before printing the next value. This is adjustable of course.

how can i transfer image from PC to Mobile via bluetooth using RFCOMM in java?

I did following coding # PC side (I tried to sent data in chunks):
try {
for (int i = 0; i < sdata.length / 2; i++)
m_Output.write(sdata[i]);
} catch (IOException ex) {
Logger.getLogger(SPPServer.class.getName()).log(Level.SEVERE, null, ex);
}
int i = sdata.length / 2;
try {
m_Output.flush();
} catch (IOException ex) {
Logger.getLogger(SPPServer.class.getName()).log(Level.SEVERE, null, ex);
}
for (int k = i; k < sdata.length; k++) {
try {
m_Output.write(sdata[i]);
m_Output.flush();
m_Output.close();
} catch (IOException ex) {
Logger.getLogger(SPPServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
While at mobile side I receive it as:
public Image recdata() {
Image image1 = null;
int i = 0;
try {
// input = StrmConn.openInputStream();
length = input.read();
data1 = new byte[length];
length = 0;
int ch = 1;
while (length != data1.length) {
ch = input.read(data1, length, data1.length - length);
if (ch == -1) {
throw new IOException("Can't read data");
}
length += ch;
}
try {
// int len = ch;
input.wait(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
length = input.read();
byte[] data11 = new byte[length];
try {
this.wait(1700);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
while (length != data11.length) {
ch = input.read(data11, length, data11.length - length);
if (ch == -1) {
throw new IOException("Can't read data");
}
length += ch;
}
length = data1.length + data11.length;
data12 = new byte[length];
for (i = 0; i < data1.length; i++) {
data12[i] = data[i];
}
for (int k = i; k < length; k++)
data12[k] = data[k];
}
catch (IOException e) {
System.err.println("U must correct");
}
if (image1 == null) {
S = "Imagr is null in recive data";
}
return image1;
}
The problem might be here on the mobile side
length = input.read();
You are (probably) assigning a byte to an integer, so when you use the value later, you're using the integer representation of the byte and not the integer value. Here is a link with code to let you convert the integer to a byte array, and then back from a byte array to an integer. Java integer to byte array

Categories

Resources