How to extract amplitude from byte array in android? - java

I am recording sound from mic using audio recorder. recoChunk byte[] store raw recording as shown below.
while (isRecording == true) {
Log.w("myMsg", "recording..");
recoChunk = new byte[minBuffSize];
audioRecord.read(recoChunk, 0, minBuffSize);
mFosRaw.write(recoChunk);
}
now from recoChunk I want to find largest amplitude recorded how can I do that?

You can cast your byte array to an array of a type that matches the bit-depth of your recorded audio in its size. For example for 16-bit audio, you can use short, since it holds a 16-bit signed integer value. For 8-bit you can just use the byte array without casting. Then, simply, the largest "number" in the array (you would probably want to take the absolute value) will be the sample with the highest amplitude value.

Related

Unknown input byte length convert to int

My android program need to receive int values from arduino analog sensor via usb and print them on real time graph, i receive byte[] from call back function.
i tried many ways to convert from byte[] to string or int include new String new Integer BigInteger parseInt and some code method that i find in other topics, but nothing work i receive only half of the correct values, other values to much bugger or smaller.
The byte[] length changed from 1 to 4 , their is some empty bytes, it look like this(log):
How i can to convert it to correct values? where the problem?
In ideal i need receive int values between 230 to 300 from sensor.
It seems that your sensor is using text protocol. If I convert your bytes to ASCII chars, it will be:
..
10-LF
50-2
53-5
56-8
..
13-CR
10-LF
50-2
53-5
..
54-6
13-CR
10-LF
etc.
Interpreted as
258
256
so, I thing the best solution is to accumulate received bytes as chars and when CRLF is reveived, read whole string (with stripped CRLF) as int - probably via parseInt.
Arduino code segment?
Guessing badly : int is a 16 bit value byte is 8 bits.
Int_8 is -128 to 127 . uint8_t 0-255 not supported by java as far as i know but you can use the char type unsigned 16 bit(need to cast it).

Java. How to get constant read times from text file?

I have text file which contains over 1kk integer numbers. I want to read the n-th number in constant time. I'm not allowed to put all integers in the array. I heard that there is a technique which operates with bytes, so I could just write method "getNthInteger(int nth, int elementLengthInBytes)" or something like that. Please give me reference to this technique, any help is appreciated!
You convert each integer to an array of bytes of some length L, then write the bytes to the file. L must be exactly the same for each integer. Then to read integer N, read L bytes starting from byte N*L.
For example:
You can write an integer to a file as 4 bytes with java.io.RandomAccessFile.writeInt(int).
You can read the Nth integer with:
java.io.RandomAccessFile.seek(n*4);
int i = java.io.RandomAccessFile.readInt();
Replace java.io.RandomAccessFile with an actual object of type java.io.RandomAccessFile.

Storing 16Bit Audio on a 8bit byte array in android

I'm confused. I needed to record sound from MIC in Android so I used the following code:
recorder = new AudioRecord(AudioSource.MIC, 44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, N);
buffer = new byte[N];
//...
recorder.read(buffer, 0, N);
As we know, a byte array can store values between -128 to +128 while a 16Bit sound needs a lot more storage(e.g. short and int) but surprisingly Java and Android have a record method which saves recorded data to a byte array.
How that can be possible? What am I missing?
You are thinking of byte as a shot integer. It is just 8 bits. You need to store 1000111011100000 (16 bits)? First byte is 10001110, second byte is 11100000. That you can interpret these bits as numbers is not relevant here. In a more general way, byte[] is usually how you deal with binary "raw data" (let it be audio streams or encrypted content or anything else that you treat like a stream of bits).
If you have n "words" of 16 bits then you will need 2n bytes to store it. Byte 0 will be lower (or higher) part of word 0, byte 1 will be the rest of word 0, byte 0 will be lower (or higher) part of word 1...

how audioRecord retrieve data with a specified sampling rate

my experiment is like this:
first, I use matlab to create a specified wave file with a rate of 44100, which means any fragment lasting 1s contains 44100 elements and these elements are presented as double.
then, I use smartphone's microphone to retrieve the wave. And the sampling rate is 44100, in order to restore the wave.
But, audioRecord store the data as byte, while what i want is double. Converting from byte to double sounds reasonable, I still confused that sampling rate 44100 means the audioRecord should record 44100 bytes in 1s or 44100*4 bytes, since double contains 4 bytes?
Other experiment i have committed:
using recording software to retrieve wave and store in .wav
read the .wav by matlab's wavread and by java respectively.
To 1s, we get 44100 elements, and list below:
-0.00164794921875
1.52587890625E-4
2.74658203125E-4
-0.003326416015625
0.001373291015625
-4.2724609375E-4
0.00445556640625
9.1552734375E-5
-9.1552734375E-4
7.62939453125E-4
-0.003997802734375
9.46044921875E-4
-0.00103759765625
0.002471923828125
0.001922607421875
-0.00250244140625
8.85009765625E-4
-0.0032958984375
8.23974609375E-4
8.23974609375E-4
anyone know how many elements the audioRecord will retrieve in 1s with the sampling rate of 44100?
The default for AudioRecord is to return 16-bits per channel for each sample (ENCODING_PCM_16BIT).
Now there are two read overloads that let you specify either a short[] (16 bits) or a byte[] (8 bits) buffer.
int read(short[] audioData, int offsetInShorts, int sizeInShorts)
int read(byte[] audioData, int offsetInBytes, int sizeInBytes)
So a 1 second mono buffer (1 channel) should have a short[] buffer of length 44100. Stereo (2 channels) would have 88200, etc...
I would avoid using the byte[] buffer unless you had set the AudioRecord format to ENCODING_PCM_8BIT for some reason (it is not guaranteed to be supported by all devices).
Now if you want to convert those short values to doubles you have to realize that the double values you record in matlab are double-precision normalized samples which are normalized from [-1 to 1] while the short values are going to be from [-32768 to 32767] so you would have to write a conversion function instead of just trying to cast the numbers from a short to a double.

Android PCM to Ulaw encoding wav file

I'm trying to encode raw pcm data as uLaw to save on the bandwidth required to transmit speech data.
I have come across a class called UlawEncoderInputStream on This page but there is no documentation! :(
The constructor takes an input stream and a max pcm value (whatever that is).
/**
* Create an InputStream which takes 16 bit pcm data and produces ulaw data.
* #param in InputStream containing 16 bit pcm data.
* #param max pcm value corresponding to maximum ulaw value.
*/
public UlawEncoderInputStream(InputStream in, int max) {
After looking through the code, I suspect that i should calculate this "max" value using a supplied function: maxAbsPcm. Problem is, i dont really understand what I'm meant to pass into it! I am recording my raw pcm to a file on the sdcard so I dont have one continuous memory resident array of data to pass to this.
/**
* Compute the maximum of the absolute value of the pcm samples.
* The return value can be used to set ulaw encoder scaling.
* #param pcmBuf array containing 16 bit pcm data.
* #param offset offset of start of 16 bit pcm data.
* #param length number of pcm samples (not number of input bytes)
* #return maximum abs of pcm data values
*/
public static int maxAbsPcm(byte[] pcmBuf, int offset, int length) {
Another problem I have using this code is I am unsure what values to write out for the header for uLaw data. How do i determine how much less byte data there is after encoding with uLaw?
I have listened to one of the (potentially) uLaw encoded files that I created in VLC media player (the only player i have that will attempt to read the file) and its sounds nasty, broken and clicky but can still make out the voice.
I am writing my wave header using code similar to a class I found called WaveHeader which can be found Here!
If anyone has any thoughts on this matter I would be most grateful to hear them!:)
Many thanks
Dexter
The max in the constructor is the maximum amplitude in the PCM data. It is used to scale the input before generating the output. If the input is very loud you need a higher value, if it's quiet you need a lower one. If you pass in 0 the encoder will use 8192 by default, which may be good enough.
The length in the other method is the number of 16-bit samples from which you want to find the maximum amplitude. This class assumes that the input PCM data is always encoded with 16-bit samples, which means that each sample spans two bytes: if your input is 2000 bytes long you have 1000 samples.
The encoder in this class produces one 8-bit ยต-Law sample for every 16-bit PCM sample, so the size in bytes is halved.
This is the opposite of what you are trying to do, but I thought it could be helpful to someone. Here is an exmple method that will convert an 8-bit uLaw encoded binary file into a 16-bit WAV file using built-in Java methods.
public static void convertULawFileToWav(String filename) {
File file = new File(filename);
if (!file.exists())
return;
try {
long fileSize = file.length();
int frameSize = 160;
long numFrames = fileSize / frameSize;
AudioFormat audioFormat = new AudioFormat(Encoding.ULAW, 8000, 8, 1, frameSize, 50, true);
AudioInputStream audioInputStream = new AudioInputStream(new FileInputStream(file), audioFormat, numFrames);
AudioSystem.write(audioInputStream, Type.WAVE, new File("C:\\file.wav"));
} catch (IOException e) {
e.printStackTrace();
}
}

Categories