///////////////////////////////////////////////////////////////////////////// /// /// Example Android Application/Activity that allows processing WAV /// audio files with SoundTouch library /// /// Copyright (c) Olli Parviainen /// //////////////////////////////////////////////////////////////////////////////// package net.surina; import java.io.File; import net.surina.soundtouch.SoundTouch; import net.surina.soundtouchexample.R; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class ExampleActivity extends Activity implements OnClickListener { TextView textViewConsole = null; EditText editSourceFile = null; EditText editOutputFile = null; EditText editTempo = null; EditText editPitch = null; CheckBox checkBoxPlay = null; StringBuilder consoleText = new StringBuilder(); /// Called when the activity is created @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_example); textViewConsole = (TextView)findViewById(R.id.textViewResult); editSourceFile = (EditText)findViewById(R.id.editTextSrcFileName); editOutputFile = (EditText)findViewById(R.id.editTextOutFileName); editTempo = (EditText)findViewById(R.id.editTextTempo); editPitch = (EditText)findViewById(R.id.editTextPitch); Button buttonFileSrc = (Button)findViewById(R.id.buttonSelectSrcFile); Button buttonFileOutput = (Button)findViewById(R.id.buttonSelectOutFile); Button buttonProcess = (Button)findViewById(R.id.buttonProcess); buttonFileSrc.setOnClickListener(this); buttonFileOutput.setOnClickListener(this); buttonProcess.setOnClickListener(this); checkBoxPlay = (CheckBox)findViewById(R.id.checkBoxPlay); // Check soundtouch library presence & version checkLibVersion(); } /// Function to append status text onto "console box" on the Activity public void appendToConsole(final String text) { // run on UI thread to avoid conflicts runOnUiThread(new Runnable() { public void run() { consoleText.append(text); consoleText.append("\n"); textViewConsole.setText(consoleText); } }); } /// print SoundTouch native library version onto console protected void checkLibVersion() { String ver = SoundTouch.getVersionString(); appendToConsole("SoundTouch native library version = " + ver); } /// Button click handler @Override public void onClick(View arg0) { switch (arg0.getId()) { case R.id.buttonSelectSrcFile: case R.id.buttonSelectOutFile: // one of the file select buttons clicked ... we've not just implemented them ;-) Toast.makeText(this, "File selector not implemented, sorry! Enter the file path manually ;-)", Toast.LENGTH_LONG).show(); break; case R.id.buttonProcess: // button "process" pushed process(); break; } } /// Play audio file protected void playWavFile(String fileName) { File file2play = new File(fileName); Intent i = new Intent(); i.setAction(android.content.Intent.ACTION_VIEW); i.setDataAndType(Uri.fromFile(file2play), "audio/wav"); startActivity(i); } /// Helper class that will execute the SoundTouch processing. As the processing may take /// some time, run it in background thread to avoid hanging of the UI. protected class ProcessTask extends AsyncTask { /// Helper class to store the SoundTouch file processing parameters public final class Parameters { String inFileName; String outFileName; float tempo; float pitch; } /// Function that does the SoundTouch processing public final long doSoundTouchProcessing(Parameters params) { SoundTouch st = new SoundTouch(); st.setTempo(params.tempo); st.setPitchSemiTones(params.pitch); Log.i("SoundTouch", "process file " + params.inFileName); long startTime = System.currentTimeMillis(); int res = st.processFile(params.inFileName, params.outFileName); long endTime = System.currentTimeMillis(); float duration = (endTime - startTime) * 0.001f; Log.i("SoundTouch", "process file done, duration = " + duration); appendToConsole("Processing done, duration " + duration + " sec."); if (res != 0) { String err = SoundTouch.getErrorString(); appendToConsole("Failure: " + err); return -1L; } // Play file if so is desirable if (checkBoxPlay.isChecked()) { playWavFile(params.outFileName); } return 0L; } /// Overloaded function that get called by the system to perform the background processing @Override protected Long doInBackground(Parameters... aparams) { return doSoundTouchProcessing(aparams[0]); } } /// process a file with SoundTouch. Do the processing using a background processing /// task to avoid hanging of the UI protected void process() { try { ProcessTask task = new ProcessTask(); ProcessTask.Parameters params = task.new Parameters(); // parse processing parameters params.inFileName = editSourceFile.getText().toString(); params.outFileName = editOutputFile.getText().toString(); params.tempo = 0.01f * Float.parseFloat(editTempo.getText().toString()); params.pitch = Float.parseFloat(editPitch.getText().toString()); // update UI about status appendToConsole("Process audio file :" + params.inFileName +" => " + params.outFileName); appendToConsole("Tempo = " + params.tempo); appendToConsole("Pitch adjust = " + params.pitch); Toast.makeText(this, "Starting to process file " + params.inFileName + "...", Toast.LENGTH_SHORT).show(); // start SoundTouch processing in a background thread task.execute(params); // task.doSoundTouchProcessing(params); // this would run processing in main thread } catch (Exception exp) { exp.printStackTrace(); } } }