3

I have a sample application in which when I press a Start button, it will start a MediaRecorder and a MediaPlayer as a guide music for the recorded music. Then after pressing Stop button it will save the recorded audio. And then, I have a third button that will play the recorded audio and also the guide audio. The problem is they are not in sync. The guide audio plays ahead of the recorded audio.

My code:

    public class MainActivity extends Activity {

         MediaRecorder recorder;
         MediaPlayer mediaPlayer;
         MediaPlayer mediaRecorded = new MediaPlayer();;
          File audiofile = null;
          private static final String TAG = "SoundRecordingActivity";
          private View startButton;
          private View stopButton;
          private View playButton;
          private View stopPlaybackButton;
          private Uri uri;

          @Override
          public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            startButton = findViewById(R.id.start);
            stopButton = findViewById(R.id.stop);
            playButton = findViewById(R.id.play);
            stopPlaybackButton = findViewById(R.id.stop_all);
          }

          public void startRecording(View view) throws IOException {

            startButton.setEnabled(false);
            stopButton.setEnabled(true);
            playButton.setEnabled(false);

            mediaPlayer = MediaPlayer.create(this, R.raw.old_mac);

            File sampleDir = Environment.getExternalStorageDirectory();
            try {
              audiofile = File.createTempFile("sound", ".mp4", sampleDir);
            } catch (IOException e) {
              Log.e(TAG, "sdcard access error");
              return;
            }
            recorder = new MediaRecorder();
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            recorder.setOutputFile(audiofile.getAbsolutePath());
            recorder.prepare();
            recorder.start();
            mediaPlayer.start();
          }

          public void stopRecording(View view) {
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            playButton.setEnabled(true);
            mediaPlayer.stop();
            recorder.stop();
            recorder.release();
            addRecordingToMediaLibrary();
          }

          protected void addRecordingToMediaLibrary() {
            ContentValues values = new ContentValues(4);
            long current = System.currentTimeMillis();
            values.put(MediaStore.Audio.Media.TITLE, "audio" + audiofile.getName());
            values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
            values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp");
            values.put(MediaStore.Audio.Media.DATA, audiofile.getAbsolutePath());
            ContentResolver contentResolver = getContentResolver();

            Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            Uri newUri = contentResolver.insert(base, values);
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri));
            Toast.makeText(this, "Added File " + newUri, Toast.LENGTH_LONG).show();

            setNewUri(newUri);

          }

          public void setNewUri(Uri uri){
              this.uri = uri;
          }

          public Uri getNewUri(){
              return this.uri;
          }

          public void playRecording(View view){
              stopPlaybackButton.setEnabled(true);
              playButton.setEnabled(false);

              mediaPlayer = MediaPlayer.create(this, R.raw.old_mac);

              try{
                  mediaRecorded.setDataSource(this, getNewUri());
                  mediaRecorded.prepare();
                  mediaRecorded.start();
                  mediaRecorded.setVolume(0, 1);


              }catch(Exception e){

              }

              mediaPlayer.start();
              mediaPlayer.setVolume(1, 0);
          }

          public void stopAll(View view){
              stopPlaybackButton.setEnabled(false);
              playButton.setEnabled(true);
              mediaPlayer.stop();
              mediaRecorded.stop();
          }

    }
elL
  • 767
  • 2
  • 14
  • 35
  • To verify, both tracks play ok, but the recorded one starts later than expected? Are you certain there isn't some delay on the track that's causing this? So, for example, if you're playing the recorded track by itself, does it start sooner? – Alex Florescu Jun 10 '13 at 13:30
  • Yes. The difference is just half beat. The recorded track starts a little bit behind the guide music. `"Are you certain there isn't some delay on the track that's causing this?"` hmm what could cause some delay? – elL Jun 10 '13 at 13:40
  • Not sure, but I'm just suggesting that it's possible that they playback is fairly synchronised, but the recorded track has some delay on it causing the difference you're seeing. See this also: http://stackoverflow.com/questions/7643338/mediarecorder-starts-with-a-1-sec-delay-how-do-i-get-rid-of-the-silence – Alex Florescu Jun 10 '13 at 13:43
  • sounds good. i'll try adopting that answer. thanks – elL Jun 10 '13 at 13:51
  • 2
    Android seems to have a variable audio latency on startup, so I don't believe you will achieve precise synchronization of playback unless you decode all tracks to the same format and mix them yourself. And you have the same issues on record, so maintaining playback-record synch will likely require some adaptive scheme for measuring the path latency *in a particular session* and then compensating for it afterwards. – Chris Stratton Jun 10 '13 at 15:06

0 Answers0