I want to read my recorded wav file and use it for signal processing with the following processing method:
//SIGNAL PROCESSING
private void proccessSignal(double[] signalIN){
double samplefreq = 44100;
double[] signal = signalIN;
Bessel bandpassfilter = new Bessel(signal,samplefreq);
double[] filteredSignal = bandpassfilter.lowPassFilter(1,150);
Bessel newsignalfiltered = new Bessel(filteredSignal,samplefreq);
double[] needsAmplifianceSignal = newsignalfiltered.bandPassFilter(1,200,500);
double[] amplifiedSignal = needsAmplifianceSignal;
for (int i=0;i<=needsAmplifianceSignal.length;i++){
amplifiedSignal[i]=amplifiedSignal[i]*1000;
amplifiedSignal[i]=amplifiedSignal[i]*amplifiedSignal[i];
}
Hilbert h = new Hilbert(amplifiedSignal);
h.hilbertTransform();
double[][] analytical_signal = h.getOutput();
Log.d("Endsignal", "proccessSignal: "+analytical_signal);
double threshold = 0.0052;
int apneaCount = 0;
for (int i=0; i<=analytical_signal.length;i++)
{
for (int j=0; j<=analytical_signal.length;j++){
if (threshold<=analytical_signal[i][j]){
}else {
apneaCount++;
if (apneaCount>=10){
apneaview.setText("YOU HAVE APNEA, CONTACT YOUR DOCTOR");
break;
}
}
}
}
if (apneaCount < 10){
apneaview.setText("YOU DO NOT HAVE APNEA");
}
}
The recording and everything works but it looks like the signal is always null so it never gets to my processing method, here's my Logcat to get a piece of detailed information about this issue:
- W/System.err: com.github.psambit9791.wavfile.WavFileException: Invalid Wav Header data, incorrect riff chunk ID
- W/System.err: at com.github.psambit9791.wavfile.WavFile.openWavFile(WavFile.java:257)
- W/System.err: at com.github.psambit9791.jdsp.io.Wav.readWav(Wav.java:70)
- W/System.err: at com.example.appnea.DetailedStat.onCreate(DetailedStat.java:82)
and here's the full activity for better understanding:
// TEST
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detailed_stat);
Intent receivedFromList = getIntent();
name = receivedFromList.getStringExtra("recordName");
path = receivedFromList.getStringExtra("recordPath");
nameview = findViewById(R.id.NAME);
pathview = findViewById(R.id.PATH);
apneaview = findViewById(R.id.APNEA);
nameview.setText("Record date: " + name);
pathview.setText("Record path: " + path);
apneaview.setText("INITIALISING DATA");
File audiofile = new File(path);
double[] signal = new double[0];
try {
String mMime = "audio/3gpp";
MediaCodec codec = MediaCodec.createDecoderByType(mMime);
/**
*
*
*/
Wav objRead1 = new Wav();
objRead1.readWav(path);
Hashtable<String, Long> propsOut = objRead1.getProperties(); // Gets the WAV file properties
double[][] signal1 = objRead1.getData("int"); // Can be 'int', 'long' 'double'
try {
loadFFMpegLibrary();
} catch (FFmpegNotSupportedException e) {
e.printStackTrace();
}
MediaExtractor mx = new MediaExtractor();
try {
mx.setDataSource(path);
} catch (IOException e) {
e.printStackTrace();
}
/**
* Finals
*/
MediaFormat mMediaFormat = mx.getTrackFormat(0);
byte[] bufbytes = new byte[(int) audiofile.length()];
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(audiofile));
buf.read(bufbytes, 0, bufbytes.length);
buf.close();
mMediaFormat.setByteBuffer("3gp", ByteBuffer.wrap(bufbytes));
codec.setCallback(new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
}
@Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
}
@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
}
@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
}
});
codec.configure(mMediaFormat, null, null, 0);
codec.start();
new Thread(() -> {
MediaCodec.BufferInfo buf_info = new MediaCodec.BufferInfo();
int outputBufferIndex = codec.dequeueOutputBuffer(buf_info, 0);
byte[] pcm = new byte[buf_info.size];
ByteBuffer[] mOutputBuffers = new ByteBuffer[buf_info.size];
mOutputBuffers[outputBufferIndex].get(pcm, 0, buf_info.size);
}).start();
sampleDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "/OfficeRecordings/");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
outputFile = sampleDir+"/"+"sample_record.3gp";
finalFile = sampleDir+"/"+"final_record.wav";
final String[] cmd = new String[]{"-y", "-i", outputFile, finalFile};
execFFmpegBinary(cmd);
} catch (IOException | WavFileException e) {
e.printStackTrace();
}
Log.d("AUDIO", "onCreate: AUDIO FILE EXIST?" + audiofile.exists());
//proccessSignal(signal);
}
private void execFFmpegBinary(final String[] command) {
FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onStart() {
Log.d("audio", "starting to load binary");
}
@Override
public void onFailure() {
Log.d("audio", "failed to load binary");
}
@Override
public void onSuccess() {
Log.d("audio", "loaded binary");
try {
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {
Log.d("audio", " starting to get audio " + "");
}
@Override
public void onProgress(String message) {
Log.d("audio", " progress getting audio from ");
}
@Override
public void onFailure(String message) {
Log.d("audio", " failed to get audio ");
}
@Override
public void onSuccess(String message) {
Log.d("audio", " success getting audio from video");
}
@Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
e.printStackTrace();
}
}
@Override
public void onFinish() {
}
});
} catch (FFmpegNotSupportedException e) {
// Handle if FFmpeg is not supported by device
}
}
// TRYING THE FFMPEG METHOD
public void loadFFMpegLibrary() throws FFmpegNotSupportedException {
if (fFmpeg == null)
fFmpeg = FFmpeg.getInstance(this);
fFmpeg.loadBinary(new FFmpegLoadBinaryResponseHandler() {
@Override
public void onFailure() {
Toast.makeText(getApplicationContext(), "Library failed to load", Toast.LENGTH_LONG).show();
}
@Override
public void onSuccess() {
Toast.makeText(getApplicationContext(), "Library loaded successfully", Toast.LENGTH_LONG).show();
}
@Override
public void onStart() {
}
@Override
public void onFinish() {
}
});
}
public void executeCommand(final String[] command) throws FFmpegCommandAlreadyRunningException {
fFmpeg.execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onSuccess(String message) {
}
@Override
public void onProgress(String message) {
}
@Override
public void onFailure(String message) {
}
@Override
public void onStart() {
}
@Override
public void onFinish() {
}
});
}
//CONVERTING TO DOUBLE ARRAY FROM BYTEARRAY
public static double[] toDoubleArray(byte[] byteArray){
int times = Double.SIZE / Byte.SIZE;
double[] doubles = new double[byteArray.length / times];
for(int i=0;i<doubles.length;i++){
doubles[i] = ByteBuffer.wrap(byteArray, i*times, times).getDouble();
}
return doubles;
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
//SIGNAL PROCESSING
private void proccessSignal(double[] signalIN){
double samplefreq = 44100;
double[] signal = signalIN;
Bessel bandpassfilter = new Bessel(signal,samplefreq);
double[] filteredSignal = bandpassfilter.lowPassFilter(1,150);
Bessel newsignalfiltered = new Bessel(filteredSignal,samplefreq);
double[] needsAmplifianceSignal = newsignalfiltered.bandPassFilter(1,200,500);
double[] amplifiedSignal = needsAmplifianceSignal;
for (int i=0;i<=needsAmplifianceSignal.length;i++){
amplifiedSignal[i]=amplifiedSignal[i]*1000;
amplifiedSignal[i]=amplifiedSignal[i]*amplifiedSignal[i];
}
Hilbert h = new Hilbert(amplifiedSignal);
h.hilbertTransform();
double[][] analytical_signal = h.getOutput();
Log.d("Endsignal", "proccessSignal: "+analytical_signal);
double threshold = 0.0052;
int apneaCount = 0;
for (int i=0; i<=analytical_signal.length;i++)
{
for (int j=0; j<=analytical_signal.length;j++){
if (threshold<=analytical_signal[i][j]){
}else {
apneaCount++;
if (apneaCount>=10){
apneaview.setText("YOU HAVE APNEA, CONTACT YOUR DOCTOR");
break;
}
}
}
}
if (apneaCount < 10){
apneaview.setText("YOU DO NOT HAVE APNEA");
}
}
}
Thank you so much for your time, I really appreciate it. Please let me know if you need any other information!