Record/capture internal sound playback of Android app and export mp3?

16,532

Solution 1

No, there's no API for getting the audio output, even for your own app (actually that's not entirely true, because you can get it through the Visualizer API, but it would be of such low quality that I doubt it would be of any use for you).

If you want that kind of functionality you'll have to implement it yourself. That is; as you start playback of sounds, mix them and write the result to a file as well. If the sounds are compressed you'll also have to take case of decoding them yourself.

Note that there's no MP3 encoder included with Android, so you'd have to supply your own MP3 encoder anyway if that's the format you want to export in.

Solution 2

As the michael said , u need to implement your own encoder and decoder for that . Visualizer is providing very low quality of data becaz we can use it to show on custom views and effects which are synchronized with equalizer.

This is the link where u will find simple decoder and encoder for MP3 file. Where they are reading data from MP3 file and putting it into new MP3 file. They had created support for some other extension too.

http://code.google.com/p/ringdroid/source/browse/#svn%2Fbranches%2Fgingerbread%2Fsrc%2Fcom%2Fringdroid

Solution 3

According to http://xzpeter.org/?p=254 it's possible to capture internal sound playback if you modify Android sources. Particularly the write function of the AudioFlinger::MixerThread class. (Note that the article is a little bit old - on the latest Android versions AudioFlinger was reorganized and write code can be now found in the threadLoop_write() function).

Quoting original solution author:

AudioFlinger is implemented under dir frameworks/base/services/audioflinger/. What we are going to do is to find the mixer output. In the file AudioFlinger.cpp, we can see AudioFlinger::MixerThread::threadLoop(), which is the working thread of the mixer, and this MixerThread is inherited from AudioFlinger::BaseThread. Then, just search the keyword mOutput->write with your best editor (vim, emacs, gedit, whatever), and we will find something like this under the threadLoop() function:

mLastWriteTime = systemTime();
mInWrite = true;
mBytesWritten += mixBufferSize;

int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;

That is the very point that mixer output buffer is transferred to hardware related codes I think, and the audio clip is in mMixbuffer, with size mixBufferSize. In this buffer, there are PCM raw audio data with 44100Hz sampling rate, 2 channels and 16 bits little endian as its param. If you write this buffer out to a file, like /data/wav.raw, you can just use adb pull to retrieve the data file to your host machine and play it with aplay:
aplay -t raw -c 2 -f S16_LE -r 44100 wav.raw

Anyway, in order to convert it to mp3 you will have to use external encoder as stated by Michael.

Share:
16,532
fxfuture
Author by

fxfuture

Updated on June 19, 2022

Comments

  • fxfuture
    fxfuture almost 2 years

    Is it possible to record the internal sound generated by the app?

    My app allows you to create and play back musical sequences.

    soundPool.play(soundIds[i], 1f, 1f, 1, 0,  Constants.TIME_RATE);
    

    I'd like to be able to record the sequence and export to mp3.

    I've looked into Audio Capture but setAudioSource (int audio_source) only seems to accept MIC recording.

    Thanks

  • fxfuture
    fxfuture almost 11 years
    Thanks Michael - any idea where best to start (documentation, tutorials etc) as I have no idea how I would mix the sounds and write them to a file?
  • Michael
    Michael almost 11 years
    The simplest scenario would if all your sounds were raw PCM of the same sample rate, number of channels, etc.; and you used a basic additive mixer. Your mixing would then consist of taking a sample from each currently active sound and adding them together, and then using the standard Java file APIs to write the result to a file. Care would have to be taken to make sure that the addition won't overflow. If you start dealing with encoding and decoding it gets more complex. You might find useful info if you google e.g. for "ffmpeg mp3 android" or "audio mixing".
  • fxfuture
    fxfuture almost 11 years
    Very helpful thanks. Found this for starters - mobilengineering.blogspot.it/2012/06/…
  • Pranav Jadav
    Pranav Jadav almost 11 years
    As the michael said , u need to implement your own encoder and decoder for that . Visualizer is providing very low quality of data becaz we can use it to show on custom views and effects synchronized with equalizer. code.google.com/p/ringdroid/source/browse/…
  • Slim_user71169
    Slim_user71169 almost 6 years
    I've just tried to save byte[] waveform to .wav file from Visualizer.OnDataCaptureListener. But the file can't play.
  • Michael
    Michael almost 6 years
    A WAV file is not just raw PCM data. It needs a header.
  • Banana droid
    Banana droid over 4 years
    I tried to write the buffer out with the below code: std::ofstream myfile; myfile.open ("/data/audiodata.raw", std::fstream::app); myfile << (char *)mSinkBuffer + offset; myfile.close(); Then I play the raw data with aplay. But all I get is the noise. Do you have any ideas?