App freezes on including a function( ) that writes file from buffer - java

I am a beginner in android development and I am stuck. Here, I am recording voice using audiorecorder instead of mediarecorder to use noise cancellation feature and I am writing a PCM file from the buffer to an output file and when I include the function for writing the file from the buffer the app just don't respond. it records and saves the file but freezes.
can somebody tell me what's wrong?
private void writeAudioDataToFile() {
// Write the output audio in byte
bufferSizeInBytes = AudioRecord.getMinBufferSize(
RECORDER_SAMPLERATE,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING
);
String filePath = "/sdcard/voice8K16bitmono.wav";
short sData[] = new short[bufferSizeInBytese/2];
FileOutputStream os = null;
try {
os = new FileOutputStream(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (isRecording) {
// gets the voice output from microphone to byte format
ar.read(sData, 0, bufferSizeInBytese/2);
Log.d("eray","Short wirting to file" + sData.toString());
try {
// // writes the data to file from buffer
// // stores the voice buffer
byte bData[] = short2byte(sData);
os.write(bData, 0, bufferSizeInBytes);
} catch (IOException e) {
e.printStackTrace();
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] short2byte(short[] sData) {
int shortArrsize = sData.length;
byte[] bytes = new byte[shortArrsize * 2];
for (int i = 0; i < shortArrsize; i++) {
bytes[i * 2] = (byte) (sData[i] & 0x00FF);
bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
sData[i] = 0;
}
return bytes;
}

I think, you are doing file writing operation in main thread (UI thread), that's why app freezes. Kindly do your file operation in another thread Eg. AsyncTask.
Keep in mind that "you do not do the operations which takes more than 5seconds & freezes app".
Here, just sharing the overview of concept to be added:
Add this innerclass inside your activity file.
static class FileAsyncTask extends AsyncTask{
#Override
protected Object doInBackground(Object[] objects) {
// do your file writing stuff here....
return null;
}
#Override
protected void onProgressUpdate(Object[] values) {
super.onProgressUpdate(values);
// update UI - if the file writig is success / failed
}
}
call this async task in your activity file when file need to be written:
new FileAsyncTask().execute(...);

Related

How can I send a string from C++ winsock to Android via TCP socket?

I want an android app and Windows C++ winsock to communicate using TCP sockets and I successfully sent a string from android to the C++ server but I cannot send string the other way around (from C++ server to Android client).
Here is the important C++ server part:
recvbuf = "Back At u \0";
cout << " \n " << recvbuf << "\n";
int iResult= send(ClientSocket, recvbuf, (int) strlen(recvbuf), 0);
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes Sent: %d\n", iResult);
And here is the android client recieving part:
class TextRcv extends AsyncTask<Void, Void, String>
{
#Override
protected String doInBackground(Void... params) {
//TO SEND A STRING
Socket clientSocket = null;
try {
clientSocket= new Socket("192.168.1.5",8889);
DataOutputStream oos= new DataOutputStream(clientSocket.getOutputStream());
oos.writeBytes(String.valueOf(mystr.length()));
oos.flush();
byte[] bufferout=mystr.getBytes();
oos.write(bufferout, 0, bufferout.length);
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
//to recieve a string
String input =null;
char[] buffin=new char[128];
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
in.read(buffin, 0, 128);
input=String.valueOf(buffin);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
return input;
}
#Override
protected void onPostExecute(String input) {
super.onPostExecute(input);
Toast toast=Toast.makeText(getApplicationContext(),input,Toast.LENGTH_LONG);
toast.show();
}
}
The C++ output says that there is no error and that 11 bytes (length of the recvbuff string) are sent. But on the android the 'input' string is always null.
Here is the c++ server output:
Start Receving
length of string recieved in bytes =14
AndroidID - Hello World...
Done
Back At u
Bytes Sent: 11
Press any key to continue . . .
String input =null;
At this point input is null.
char[] buffin=new char[128];
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
in.read(buffin, 0, 128);
input=String.valueOf(buffin);
This code is not correct, but if it executes at all, input cannot possibly be null. The correct code is as follows:
int count = in.read(buffin);
if (count > 0)
{
input = new String(buffin, 0, count);
}
Back to your code:
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
return input;
If input is still null at this point, there must have been an IOException which you haven't disclosed.

File is not received unless i call os.close()

I am sending file from server to client using java socket programming.
Here is my server side code:
public void fileSendingProtocol(String filePath) {
File myFile = new File(filePath);
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = null;
try {
fis = new FileInputStream(myFile);
} catch (FileNotFoundException ex) {
System.err.println(ex);
}
BufferedInputStream bis = new BufferedInputStream(fis);
try {
bis.read(mybytearray, 0, mybytearray.length);
os.write(mybytearray, 0, mybytearray.length);
os.flush();
System.out.println(filePath + " Submitted");
// File sent, exit the main method
} catch (IOException ex) {
// Do exception handling
System.out.println(ex.toString());
} finally {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here i have closed the os in the finally block. Because if i omit os.close() then i am not able to receive the file in the client side.
Here is my client file receiving code:
public static void fileReceivingProtocol(String filePath) {
try {
fos = new FileOutputStream(filePath);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
bos = new BufferedOutputStream(fos);
/* read question paper from the server. */
try {
bytesRead = is.read(aByte, 0, aByte.length);
do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);
bos.write(baos.toByteArray());
bos.flush();
fos.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
I need the server first send a file . Then after receiving that file the client need to send another file to server after some minutes. But if i call the os.close() in the server side then my socket get closed and i am not able to continue any further communication between then.
You do not need to close os (the OutputStream), just call its flush() method. Streams are often buffered for performance reasons. A call to flush() will instruct the implementation to send all cached data.
Most likely the file you send is small (maybe a few KB at the most) which is less than the typical cache size. If you write less data than the cache size (or the data that can be transmitted in a TCP packet in case of a Socket's OutputStream), the implementation will likely not send it for some time. flush() will send whatever data there is cached.
If your client does not know the file size (does not know how many bytes to wait for), you have to implement some kind of "protocol" to exchange these information. A very basic would be to first send the file size (number of bytes) in 4 bytes (that is the size of a Java int), and then send the content of the file.
The client will know that the first 4 bytes will be the file size, and it will wait for / read that amount of bytes.
How to convert int to bytes: Convert integer into byte array (Java) or Java integer to byte array
Modified file sender
// First write the file's length (4 bytes)
int length = (int) myFile.length();
os.write((length >>> 24) & 0xff);
os.write((length >>> 16) & 0xff);
os.write((length >>> 8) & 0xff);
os.write(length & 0xff);
// And now send the content of the file just as you did
Modified file receiver
// First read the file's length (4 bytes)
int b1 = is.read();
int b2 = is.read();
int b3 = is.read();
int b4 = is.read();
if (b1 < 0 || b2 < 0 || b3 < 0 || b4 < 0)
throw new EOFException(); // Less than 4 bytes received, end of stream
int length = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
// And now read the content of the file which must be exactly length bytes

java playing sounds in order

Hi I have following java programme that play some sounds.I want to play sounds in order for example after ending of sound1 i want to play sound2 and then sound3 the following is my java code and function of playing sound .
private void playsound(String file)
{
try {
crit = AudioSystem.getClip();
AudioInputStream inputStream1 = AudioSystem.getAudioInputStream(this.getClass().getResource(file));
crit.open(inputStream1);
//if(!crit.isOpen())
{
crit.start();
}
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
and calling it as following
playsound("/sounds/filesound1.au");
playsound("/sounds/filesound2.au");
playsound("/sounds/filesound3.au");
the programme is plying sound in parallel which I don't want.I want to play in order
Regards
I got the following code from somewhere that I can't remember right now but it plays the music consequently:
public static void play(ArrayList<String> files){
byte[] buffer = new byte[4096];
for (String filePath : files) {
File file = new File(filePath);
try {
AudioInputStream is = AudioSystem.getAudioInputStream(file);
AudioFormat format = is.getFormat();
SourceDataLine line = AudioSystem.getSourceDataLine(format);
line.open(format);
line.start();
while (is.available() > 0) {
int len = is.read(buffer);
line.write(buffer, 0, len);
}
line.drain();
line.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The reason this plays the files consequently and not all at the same time is because write blocks until the requested amount of data has been written. This applies even if the requested amount of data to write is greater than the data line's buffer size.
Make sure to include drain() from the code above. drain() waits for the buffer to empty before it close()s.

Asynchronous consumption of InputStream

I want to play streaming media, received from a internet service. The media player works fine, but is sometimes interrupted due to poor download rate.
On receiving of media data I run a thread that does decoding and other manipulations, the abstract code looks like that:
private void startConsuming(final InputStream input) {
consumingThread = new Thread() {
public void run() {
runConsumingThread(input);
}
};
consumingThread.start();
}
My idea is to calculate the buffer size needed to prevent interruption, and to start media playback once the buffer is filled (or, of cause, if the stream ends).
private void startConsuming(final InputStream input) {
consumingThread = new Thread() {
public void run() {
runConsumingThread(input);
}
};
Thread fillBufferThread = new Thread() {
public void run() {
try {
while(input.available() < RECEIVING_BUFFER_SIZE_BYTES) {
log.debug("available bytes: " + input.available());
sleep(20);
}
} catch (Exception ex) {
// ignore
}
consumingThread.start();
}
};
fillBufferThread.start();
}
In debug I get continuously "available bytes: 0" while stream arrives and does not break the while loop. I recognized already, that EOFException will of cause not occur, since I do not read from InputStream.
How can I handle this? I thought that input.available() would increase on data arrival.
Why can runConsumingThread(input) work correctly in nearly the same manner, but my while loop in fillBufferThread does not?
EDIT: Following code nearly works (except that it wrongly consumes the input stream, which is then not played in consumingThread, but that will be easy to solve), but there must be a smarter solution.
[...]
Thread fillBufferThread = new Thread() {
public void run() {
final DataInputStream dataInput = new DataInputStream(input);
try {
int bufferSize = 0;
byte[] localBuffer = new byte[RECEIVING_BUFFER_SIZE_BYTES];
while(bufferSize < RECEIVING_BUFFER_SIZE_BYTES) {
int len = dataInput.readInt();
if(len > localBuffer.length){
if (D) log.debug("increasing buffer length: " + len);
localBuffer = new byte[len];
}
bufferSize += len;
log.debug("available bytes: " + bufferSize);
dataInput.readFully(localBuffer, 0, len);
}
consumingThread.start();
}
};
[...]
It can't be efficient to read from stream until I know, that I have it filled with a number of bytes, or is it?

How do I record audio on Android and change the pitch?

I am trying to learn Android Development and I was wondering how I can capture audio from a microphone and then change the voice in the audio so that it sounds thicker or sharper etc.
In short: How do I record and change the parameters of a sound? (In java, of course)
I'm actually working on an android app that involves audio. Recording the audio is the easy part, and you can mostly copy my code for that. Writing an audio filter is a much harder task, and requires knowledge of digital signal processing and the Fast Fourier Transform (FFT)
You could start by reading about audio processing in java here.
Meanwhile, here's the code to record audio on android:
public String record() {
// please note: the emulator only supports 8 khz sampling.
// so in test mode, you need to change this to
//int frequency = 8000;
int frequency = 11025;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/reverseme.pcm");
// Delete any previous recording.
if (file.exists())
file.delete();
// Create the new file.
try {
file.createNewFile();
} catch (IOException e) {
throw new IllegalStateException("Failed to create "
+ file.toString());
}
try {
// Create a DataOuputStream to write the audio data into the saved
// file.
OutputStream os = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
// Create a new AudioRecord object to record the audio.
int bufferSize = 2 * AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
Log.e(tag, "Recording started");
long start = SystemClock.elapsedRealtime();
long end = start + 15000;
while (SystemClock.elapsedRealtime() < end) {
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++)
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
dos.writeShort( EndianUtils.swapShort(buffer[i]));
} else {
dos.writeShort( buffer[i] );
}
}
Log.e(tag, "Recording stopped");
audioRecord.stop();
bos.flush();
dos.close();
isRecording = false;
return file.getAbsolutePath();
} catch (Exception e) {
Log.e(tag, "Recording Failed:" + e.getMessage());
throw new RuntimeException("Failed to create " + e.getMessage());
}
}
You can use Android SoundPool to chnage the pitch of audio file check answers of THIS question.
And to record audio when someone speaks near MIC check this LINK.

Categories