I've trying to create a single synchronous audio output file from two or more than two audio files of same length. I have done some research and came to know that this can be achieved through below steps:
- Only uncompressed audio files can be used for this purpose. i.e. Convert mp3 audio files into WAV format.
- Mix 2 new wav files; i have followed this approach: Mix audio in android
But the same problem arises, the mixed audio file doesn't play.
I've been trying to add a valid header to the output file as per this answer Writing PCM recorded data into a .wav file (java android).
Here is my Mixer class:
public class SongMixer2
{
private Context mContext;
public SongMixer2(Context context)
{
mContext = context;
}
public void onCreate()
{
try
{
mixSound();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void mixSound() throws IOException
{
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
44100, AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT, 44100, AudioTrack.MODE_STREAM);
InputStream in1 = mContext.getResources().openRawResource(R.raw.brokaw);
InputStream in2 = mContext.getResources().openRawResource(R.raw.brokaw);
byte[] arrayMusic1 = null;
arrayMusic1 = new byte[in1.available()];
arrayMusic1 = createMusicArray(in1);
in1.close();
byte[] arrayMusic2 = null;
arrayMusic2 = new byte[in2.available()];
arrayMusic2 = createMusicArray(in2);
in2.close();
byte[] output = new byte[arrayMusic1.length];
audioTrack.play();
for (int i = 0; i < output.length - 1; i++)
{
float samplef1 = arrayMusic1[i] / 128.0f;
float samplef2 = arrayMusic2[i] / 128.0f;
float mixed = samplef1 + samplef2;
// reduce the volume a bit:
mixed *= 0.8;
// hard clipping
if (mixed > 1.0f)
mixed = 1.0f;
if (mixed < -1.0f)
mixed = -1.0f;
byte outputSample = (byte) (mixed * 128.0f);
output[i] = outputSample;
}
audioTrack.write(output, 0, output.length);
convertByteToFile(output);
}
public static byte[] createMusicArray(InputStream is) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buff = new byte[10240];
int i = Integer.MAX_VALUE;
while ((i = is.read(buff, 0, buff.length)) > 0)
{
baos.write(buff, 0, i);
}
return baos.toByteArray(); // be sure to close InputStream in calling
// function
}
public static void convertByteToFile(byte[] fileBytes)
throws FileNotFoundException
{
String path = Environment.getExternalStorageDirectory().getPath() + "/mixed.wav";
File f=new File(path);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(f));
try
{
bos.write(writeHeader(fileBytes.length), 0, 44);
bos.write(fileBytes);
bos.flush();
bos.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static byte[] writeHeader(int totalDataLen)
{
byte[] header = new byte[44];
header[0] = 'R'; // RIFF/WAVE header
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
header[12] = 'f'; // 'fmt ' chunk
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
header[16] = 16; // 4 bytes: size of 'fmt ' chunk
header[17] = 0;
/* header[18] = 0;
header[19] = 0;
header[20] = 1; // format = 1
header[21] = 0;
header[22] = (byte) channels;
header[23] = 0;
header[24] = (byte) (longSampleRate & 0xff);
header[25] = (byte) ((longSampleRate >> 8) & 0xff);
header[26] = (byte) ((longSampleRate >> 16) & 0xff);
header[27] = (byte) ((longSampleRate >> 24) & 0xff);
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
header[32] = (byte) (2 * 16 / 8); // block align
header[33] = 0;
header[34] = RECORDER_BPP; // bits per sample
header[35] = 0;*/
header[36] = 'd';
header[37] = 'a';
header[38] = 't';
header[39] = 'a';
/* header[40] = (byte) (totalAudioLen & 0xff);
header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
*/
return header;
}
}
And the Activity:
public class SoundMixerActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
new SongMixer2(this).onCreate();
}
}
A File 'mixed.wav' is created there in SD card, but it won't play...anyone please help!!