1. Download our Official Android App: Forums for Android!

(SOLVED) how to read data from streamed mic with tarsos bandpass filter

Discussion in 'Android Development' started by RoadhammerGaming, Aug 24, 2017.

  1. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    Hello, I'm trying to implement a simple bandpass filter in my project, but can't seem to read the output data.

    Notes: I'm using android studio and currently I'm using the latest tarsos audio library that is supposed to be compatible with android, and in fact have successfully added the library to my android studio project. I previously tried using the JTransforms and the Minim libraries with no luck. EDITED 8/23/17: found and fixed some bugs, reposted current code, still made no progress with the actual problem summarized below:

    Summary: in the 5th code block I have posted, on line 15 that is commented out, I need to know how to get that line to work, as I can't get the data that needs to be read

    What I'm trying to do is record from the microphone, and while recording use the dsp BandPass filter from the tarsos library and output the results to a .wav file. I can successfully stream the microphone to a .wav file following this tutorial by using the android.media imports, but that doesn't allow me to add the BandPass filter, and using the tarsos imports functions don't allow me to use the save as .wav methods that that tutorial has, I know I'm missing something and/or doing something wrong, but I've been googling this for almost a week and haven't found a working solution, I've only found links to the java files that are inside the library which isn't helpful as I couldn't find tutorials on how to correctly use them. What am I doing wrong? Here is the relevant code for the tarsos method I'm trying to use:

    the related imports and 'global' variables

    Code (Java):
    1.     import android.media.AudioRecord;
    2.     import android.media.MediaRecorder;
    3.     import android.media.AudioFormat;
    4.     import android.media.AudioTrack;
    5.  
    6.     import be.tarsos.dsp.AudioDispatcher;
    7.     import be.tarsos.dsp.AudioProcessor;
    8.     import be.tarsos.dsp.filters.BandPass;
    9.     import be.tarsos.dsp.io.android.AudioDispatcherFactory;
    10.  
    11.     //start the class
    12.  
    13.     AudioRecord alteredRecord = null;
    14.     AudioDispatcher dispatcher;
    15.     float freqChange;
    16.     float tollerance;
    17.     private static final int RECORDER_BPP = 16;
    18.     private static final String AUDIO_RECORDER_FOLDER = "Crowd_Speech";
    19.     private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
    20.     private static final int RECORDER_SAMPLERATE = 44100;
    21.     private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
    22.     private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
    23.     private int bufferSize = 1024;
    24.     private Thread recordingThread = null;
    25.  
    26.     //set the min buffer size in onCreate event
    27.  
    28.     bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
    29.     RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING)*4;
    This starts the mic recording inside an onClick method, and by commenting/uncommenting one of the 2 'running' variable values I can switch between filter or no filter (android or tarsos functions) when the startRecording method is called

    Code (Java):
    1.  if(crowdFilter && running==0 && set==0){//crowd speech mode, start talking
    2.     Icons(2,"");
    3.     running=4;//start recording from mic, apply bandpass filter and save as wave file using TARSOS import
    4.     //running=5;//start recording from mic, no filter, save as wav file using android media import
    5.    freqChange = Globals.minFr[Globals.curUser];
    6.     tollerance = 40;
    7.     set=1;
    8.     startRecording();
    9.     }
    The start recording method:

    Code (Java):
    1.  private void startRecording() {
    2.  
    3.        if (running == 5) {//start recording from mic, no filter, save as wav file using android media library
    4.            alteredRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);
    5.            alteredRecord.startRecording();
    6.            isRecording = true;
    7.            recordingThread = new Thread(new Runnable() {
    8.                @Override
    9.                public void run() {
    10.                    writeAudioDataToFile();
    11.                }
    12.            }, "Crowd_Speech Thread");
    13.            recordingThread.start();
    14.        }
    15.  
    16.       if (running == 4) {//start recording from mic, apply bandpass filter and save as wave file using TARSOS library
    17.        dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(RECORDER_SAMPLERATE, bufferSize, 0);
    18.        AudioProcessor p = new BandPass(freqChange, tollerance, RECORDER_SAMPLERATE);
    19.        dispatcher.addAudioProcessor(p);
    20.            isRecording = true;
    21.            dispatcher.run();
    22.            recordingThread = new Thread(new Runnable() {
    23.                @Override
    24.                public void run() {
    25.                    writeAudioDataToFile();
    26.                }
    27.            }, "Crowd_Speech Thread");
    28.            recordingThread.start();
    29.       }
    30.     }
    Stop recording button inside an onClick method

    Code (Java):
    1.  if(crowdFilter && (running==4 || running==5) && set==0) {//crowd speech finished talking
    2.        Icons(1, "");
    3.        stopRecording();
    4.        set = 1;
    5.     }
    Both cases are fine until this point, if running==4 (tarsos dsp filter applied) the program won't compile unless the data read line is commented out. if I use running==5 (the android.media way with no filter) the whole rest of this works fine and saves the file, but no BandPass effect applied. if I try swapping out the alteredRecord = new AudioRecord... with the tarsos dispatcher = AudioDispatcherFactory... ( such as dispatcher = new AudioRecord...) they are incompatible and will not even think of compiling. (That's why line 15 in the following method is commented out)

    Code (Java):
    1.  private void writeAudioDataToFile(){
    2.        byte data[] = new byte[bufferSize];
    3.        String filename = getTempFilename();
    4.        FileOutputStream os = null;
    5.        try {
    6.            os = new FileOutputStream(filename);
    7.        } catch (FileNotFoundException e) {
    8.            e.printStackTrace();
    9.        }
    10.        int read = 0;
    11.        if(null != os){
    12.        while(isRecording){
    13.            if(running==4)
    14.            {
    15.                //read = dispatcher.(data, 0, bufferSize);
    16.            }
    17.            if(running==5)
    18.            {
    19.                read = alteredRecord.read(data, 0, bufferSize);
    20.            }
    21.            if(AudioRecord.ERROR_INVALID_OPERATION != read){
    22.                try {
    23.                    os.write(data);
    24.                } catch (IOException e) {
    25.                    e.printStackTrace();
    26.                }
    27.            }
    28.        }
    29.        try {
    30.            os.close();
    31.        } catch (IOException e) {
    32.            e.printStackTrace();
    33.        }
    34.        }
    35.     }
    36.  
    37.     private void stopRecording(){
    38.     if(null != alteredRecord) {
    39.        isRecording = false;
    40.        int i = alteredRecord.getState();
    41.        if (i == 1) {
    42.            running = 0;
    43.            alteredRecord.stop();
    44.            alteredRecord.release();
    45.            alteredRecord = null;
    46.            recordingThread = null;
    47.        }
    48.      }
    49.        if(null !=dispatcher){
    50.            isRecording = false;
    51.            running = 0;
    52.            dispatcher.stop();
    53.            recordingThread = null;
    54.        }
    55.      copyWaveFile(getTempFilename(),getFilename());
    56.      deleteTempFile();
    57.     }
    58.  
    59.     private void deleteTempFile() {
    60.        File file = new File(getTempFilename());
    61.        file.delete();
    62.     }
    63.  
    64.     private void copyWaveFile(String inFilename,String outFilename){
    65.        FileInputStream in = null;
    66.        FileOutputStream out = null;
    67.        long totalAudioLen = 0;
    68.        long totalDataLen = totalAudioLen + 36;
    69.        long longSampleRate = RECORDER_SAMPLERATE;
    70.        int channels = 1;
    71.        long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;
    72.        byte[] data = new byte[bufferSize];
    73.        try {
    74.        in = new FileInputStream(inFilename);
    75.        out = new FileOutputStream(outFilename);
    76.        totalAudioLen = in.getChannel().size();
    77.        totalDataLen = totalAudioLen + 36;
    78.        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
    79.                longSampleRate, channels, byteRate);
    80.        while(in.read(data) != -1){
    81.            out.write(data);
    82.        }
    83.        in.close();
    84.        out.close();
    85.        } catch (FileNotFoundException e) {
    86.            e.printStackTrace();
    87.        } catch (IOException e) {
    88.            e.printStackTrace();
    89.        }
    90.     }
    91.  
    92.     private void WriteWaveFileHeader(
    93.        FileOutputStream out, long totalAudioLen,
    94.        long totalDataLen, long longSampleRate, int channels,
    95.        long byteRate) throws IOException {
    96.      byte[] header = new byte[44];
    97.      header[0] = 'R';header[1] = 'I'; header[2] = 'F';header[3] = 'F';// RIFF/WAVE header
    98.      header[4] = (byte) (totalDataLen & 0xff);
    99.      header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    100.      header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    101.      header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    102.      header[8] = 'W';header[9] = 'A';header[10] = 'V';header[11] = 'E';header[12] = 'f';header[13] = 'm';header[14] = 't';header[15] = ' ';// 'fmt ' chunk
    103.      header[16] = 16;header[17] = 0;header[18] = 0;header[19] = 0;// 4 bytes: size of 'fmt ' chunk
    104.      header[20] = 1;header[21] = 0;header[22] = (byte) channels;header[23] = 0;// format = 1
    105.      header[24] = (byte) (longSampleRate & 0xff);header[25] = (byte) ((longSampleRate >> 8) & 0xff);header[26] = (byte) ((longSampleRate >> 16) & 0xff);
    106.      header[27] = (byte) ((longSampleRate >> 24) & 0xff);header[28] = (byte) (byteRate & 0xff);header[29] = (byte) ((byteRate >> 8) & 0xff);
    107.      header[30] = (byte) ((byteRate >> 16) & 0xff); header[31] = (byte) ((byteRate >> 24) & 0xff);
    108.      header[32] = (byte) (2 * 16 / 8);header[33] = 0;// block align
    109.      header[34] = RECORDER_BPP;header[35] = 0;header[36] = 'd';header[37] = 'a';header[38] = 't';header[39] = 'a';
    110.      header[40] = (byte) (totalAudioLen & 0xff);header[41] = (byte) ((totalAudioLen >> 8) & 0xff);header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
    111.      header[43] = (byte) ((totalAudioLen >> 24) & 0xff);// bits per sample
    112.      out.write(header, 0, 44);
    113.     }


     

    Advertisement

    #1 RoadhammerGaming, Aug 24, 2017
    Last edited: Aug 24, 2017
  2. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
    If the app crashed there will be a stack trace in the Logcat view. Please post that.
     
  3. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    sorry I'll have to edit that part of my question, I was at the time using
    Code (Java):
    1. read = alteredRecord.read(data, 0, bufferSize);
    when trying to use the tarsos library function, the error I was getting in the logcat was that the buffer size was -2, and it was because alteredRecord was null, the problem seems to be that
    Code (Java):
    1. read = dispatcher.(data, 0, bufferSize);
    is an invalid call, the program won't compile and run if that line is uncommented.[​IMG]
     
  4. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
    This isn't valid Java code

    Code (Text):
    1.  
    2. read = dispatcher.(data, 0, bufferSize);
    3.  
    What method on the AudioDispatcher class are you trying to call?
     
  5. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    EDITED

    This is the tarsos part of the method that calls the writeAudioDataToFile method:
    Code (Java):
    1. private void startRecording() {
    2.  
    3.    if (running == 4) {//start recording from mic, apply bandpass filter and save as wave file using TARSOS library
    4.         dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(RECORDER_SAMPLERATE, bufferSize, 0);
    5.         AudioProcessor p = new BandPass(freqChange, tollerance, RECORDER_SAMPLERATE);
    6.         dispatcher.addAudioProcessor(p);
    7.             isRecording = true;
    8.             dispatcher.run();
    9.             recordingThread = new Thread(new Runnable() {
    10.                 @Override
    11.                 public void run() {
    12.                     writeAudioDataToFile();
    13.                 }
    14.             }, "Crowd_Speech Thread");
    15.             recordingThread.start();
    16.     }
    17. }
    18.  
     
  6. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    the thing is that that is perfectly valid code when using the android.media import's function, it gives no errors and fully works, but does not work with the tarsos equivolent
     
  7. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
    I'm sorry but this is not valid code under any circumstances

    Code (Text):
    1.  
    2. read = dispatcher.(data, 0, bufferSize);
    3.  
    Whereas this would be valid

    Code (Text):
    1.  
    2. read = dispatcher.read(data, 0, bufferSize);
    3.  
     
  8. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    Oh yea I see what you are saying there, you're right, it is written the way you have it in the case of using the android.media function, but when I try it that way with the tarsos function the read in dispatcher.read() statement is the color red (not recognized as a valid method call error)
     
  9. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
  10. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    @LV426 here's a pic to illistrate what I mean including the actual error text (which is different from what I said in my previous post sorry): [​IMG]
     
  11. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    Ok thanks I will look at that link, but like I said in my OP I haven't been able to find any example codes that show how to get the data, just the ones on github that are source codes for the library
     
  12. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
    See above. read() is not defined in this class. It does have readNextAudioBlock(). Maybe that's what you should use?
     
  13. LV426

    LV426 I say we take off and nuke this place from orbit
    Moderator
    Rank:
     #11
    Points:
    1,988
    Posts:
    7,844
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    7,844
    11,445
    1,988
    Male
    Software developer
    South West of England
    scary alien and RoadhammerGaming like this.
  14. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    Thanks, I have been through all those examples a dozen times allready but can't find any that show how to read the output data so it can be saved from a stream to a file, I've really run out of ideas but thanks for trying to help I appreciate it
     
  15. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    The closest thing I have found was this in the issues tracker on github, but the issue was never answered and the poster claimed it didn't work so I didn't try it, I may try it now because I'm desperate, but I'm not expecting it to work
     
  16. RoadhammerGaming

    Thread Starter
    Rank:
    None
    Points:
    15
    Posts:
    15
    Joined:
    Aug 24, 2017

    Aug 24, 2017
    15
    0
    15
    Wowwwwww that broken example actually worked with a bit of modification!!! this is what I did in my startRecording method when running == 4:
    Code (Java):
    1.         if (running == 4) {//start recording from mic, apply bandpass filter and save as wave file using TARSOS library
    2.             dispatcher = AudioDispatcherFactory.fromDefaultMicrophone(RECORDER_SAMPLERATE, bufferSize, 0);
    3.             AudioProcessor p = new BandPass(freqChange, tollerance, RECORDER_SAMPLERATE);
    4.             dispatcher.addAudioProcessor(p);
    5.             isRecording = true;
    6.             // Output
    7.             RandomAccessFile outputFile = new RandomAccessFile(getFilename(), "rw");
    8.             TarsosDSPAudioFormat outputFormat = new TarsosDSPAudioFormat(44100, 16, 1, true, false);
    9.             WriterProcessor writer = new WriterProcessor(outputFormat, outputFile);
    10.             dispatcher.addAudioProcessor(writer);
    11.             recordingThread = new Thread(new Runnable() {
    12.                 @Override
    13.                 public void run() {
    14.                     dispatcher.run();
    15.                 }
    16.             }, "Crowd_Speech Thread");
    17.             recordingThread.start();
    18.         }
    I didn't even need to use any further methods (except the stopRecording method called from a button click of course) !! Thanks @LV426 for re-pointing me in the right direction, I would never have gone back to github if you hadn't coaxed me to!
     
  17. Numan Celik

    Numan Celik Lurker
    Rank:
    None
    Points:
    5
    Posts:
    1
    Joined:
    May 5, 2018

    May 5, 2018
    1
    0
    5
    Hi,
    Dear @RoadhammerGaming could you please send me the project of Android studio, then I can use it for my development. I also want to filter the recorded audio data for my project which is very similar here.
    I would be very much appreciated.
    Thanks..
     

Share This Page

Loading...