2

I'm working on a test app to integrate soundtouch (an open source audio processing library) on Android.

My test app already can receive input from the mic, pass the audio thru soundtouch and output the processed audio to an AudioTrack instance.

My question is, how can I change the output from AudioTrack to a new File on my device?

Here's the relevant code in my app (where I'm processing the output of soundtouch, into the input for AudioTrack)

// the following code is a stripped down version of my code
// in no way its supposed to compile or work.  Its here for reference purposes
// pre-conditions 
// parameters -  input : byte[]
soundTouchJNIInstance.putButes(input);
int bytesReceived = soundTouchJNIInstance.getBytes(input);
audioTrackInstance.write(input, 0, bytesReceived);

Any ideas on how to approach this problem? Thanks!

dornad
  • 1,274
  • 3
  • 17
  • 36

6 Answers6

0

I think the best way to achieve this is converting that audio to a byte[] array. Assuming you have already done that (if not, comment it and I'll provide an example), the above code should work. This assumes you're saving it in a external sdcard in a new directory called AudioRecording and saving it as audiofile.mp3.

final File soundFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "AudioRecording/");
soundFile.mkdirs();
final File outFile = new File(soundFile, 'audiofile.mp3');

try {
  final FileOutputStream output = new FileOutputStream(outFile);
  output.write(yourByteArrayWithYourAudioFileConverted);
  output.close();
} catch (FileNotFoundException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

mkdirs() method will try to construct all the parent directories if they're missing. So if you're planning to store in a 2 or more level depth directory, this will create all the structure.

nKn
  • 13,691
  • 9
  • 45
  • 62
0

Hope you are already getting the input voice from microphone and saved on a file.

Firstly, import JNI libraries to your oncreate method :

System.loadLibrary("soundtouch");
System.loadLibrary("soundstretch");

Soundstrech library :

public class AndroidJNI extends SoundStretch{
    public final static SoundStretch soundStretch = new SoundStretch();
}

Now you need to call soundstrech.process with the input file path and the desired output file to store processed voice as parameters :

AndroidJNI.soundStretch.process(dataPath + "inputFile.wav", dataPath + "outputFile.wav", tempo, pitch, rate);
        File sound = new File(dataPath + "outputFile.wav");
        File sound2 = new File(dataPath + "inputFile.wav");       
        Uri soundUri = Uri.fromFile(sound);

The soundUri can be provided as a source to media player for play back :

MediaPlayer mediaPlayer = MediaPlayer.create(this, soundUri);
        mediaPlayer.start();

Also note that, the sample size for recording should be selected dynamically by declaring an Array of Sample Rates :

int[] sampleRates = { 44100, 22050, 11025, 8000 }
Timson
  • 1,337
  • 3
  • 19
  • 32
  • I can not get SoundStretch class.. what should i do?? I m getting **SoundStretch cannot be resolved to a type** because import not working **import org.tecunhuman.jni.SoundStretch;** – WonderSoftwares Jun 26 '14 at 10:37
0

The best way to write byteArray this :

public void writeToFile(byte[] array) 
{ 
    try 
    { 
        String path = "Your path.mp3"; 
        File file = new File(path);
        if (!file.exists()) {
        file.createNewFile();
        }

        FileOutputStream stream = new FileOutputStream(path); 
        stream.write(array); 
    } catch (FileNotFoundException e1) 
    { 
        e1.printStackTrace(); 
    } 
} 
Harshit Rathi
  • 1,862
  • 2
  • 18
  • 25
0

I am not aware of sound touch at all and the link i am providing no where deals with jni code, but you can have a look at it if it helps you any way: http://i-liger.com/article/android-wav-audio-recording

Calvin
  • 617
  • 1
  • 12
  • 34
0

I use a simple test code snippet to write my audio byte arrays:

public void saveAudio(byte[] array, string pathAndName)
{
  FileOutputStream stream = new FileOutputStream(pathAndName);
  try {
      stream.write(array);
  } finally {
      stream.close();
  }
}

You will probably need to add some exception handling if you are going to be using this in a production environment, but I utilise the above to save audio whenever I am am in the development phase or for personal non-release projects.

Addendum

After some brief thought I have changed my snippet to the following slightly more robust format:

public void saveAudio(byte[] array, string pathAndName)
{
  try (FileOutputStream stream= new FileOutputStream(pathAndName)) {
      stream.write(array);
  } catch (IOException ioe) {
      ioe.printStackTrace();
  } finally {
      stream.close();
  }
}
GMasucci
  • 2,834
  • 22
  • 42
0

You can use the method using SequenceInputStream, in my app I just merge MP3 files in one and play it using the JNI Library MPG123, but I tested the file using MediaPlayer without problems.

This code isn't the best, but it works...

private void mergeSongs(File mergedFile,File...mp3Files){
        FileInputStream fisToFinal = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(mergedFile);
            fisToFinal = new FileInputStream(mergedFile);
            for(File mp3File:mp3Files){
                if(!mp3File.exists())
                    continue;
                FileInputStream fisSong = new FileInputStream(mp3File);
                SequenceInputStream sis = new SequenceInputStream(fisToFinal, fisSong);
                byte[] buf = new byte[1024];
                try {
                    for (int readNum; (readNum = fisSong.read(buf)) != -1;)
                        fos.write(buf, 0, readNum);
                } finally {
                    if(fisSong!=null){
                        fisSong.close();
                    }
                    if(sis!=null){
                        sis.close();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fos!=null){
                    fos.flush();
                    fos.close();
                }
                if(fisToFinal!=null){
                    fisToFinal.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } 
Benjamin RD
  • 11,516
  • 14
  • 87
  • 157