Audio Appending using RandomAccessFile - android

I use the following code to append as many wav files present in the sdcard to a single file. audFullPath is an arraylist containing the path of the audiofiles. Is it correct. When I play the recordedaudio1, after doing this. It play only the first file. I want to play all the files. Any suggestion..
File file=new File("/sdcard/AudioRecorder/recordedaudio1.wav");
RandomAccessFile raf = new RandomAccessFile(file, "rw");
for(int i=0;i<audFullPath.size();i++) {
f=new File(audFullPath.get(i));
fileContent = new byte[(int)f.length()];
System.out.println("Filecontent"+fileContent);
raf.seek(raf.length());
raf.writeBytes(audFullPath.get(i));
}

You can't append WAV files the way you do. That's because each WAV has special format:
The simplest possible WAV file looks like this:
[RIFF HEADER]
...
totalFileSize
[FMT CHUNK]
...
audioFormat
frequency
bytesPerSample
numberOfChannels
...
[DATA CHUNK]
dataSize
<audio data>
What you need to do is:
Make sure that all WAV files are of compatible: same audioFormat, frequency, bits per sample, number of channels, etc.
Create proper RIFF header with total file size
Create proper FMT header
Create proper DATA header with total audio data size
This algorithm will definitely work for LPCM, ULAW, ALAW audio formats. Not sure about others.

Related

Get audio input stream from a locale file on android

I am trying to get the audio input stream from a file in the local file system on an android device.
This is so that i can use this library to show a wave form for the audio file.
https://github.com/newventuresoftware/WaveformControl/blob/master/app/src/main/java/com/newventuresoftware/waveformdemo/MainActivity.java#L125
The example in the project uses rawResource like so
InputStream is = getResources().openRawResource(R.raw.jinglebells);
This input stream is later converted into byte array and passed to somewhere that uses it to paint a wave picture and sound.
however when I did
InputStream is = new InputFileSystem(new File(filePath));
But this does not seem to work properly. The image generated is wrong, and the sound played is nothing like what the file actually is.
This is the body of the function in that library that gets the input stream and convert it into byte arrays.
private short[] getAudioSample() throws IOException {
// If i replace this part with new FileInput(new File(filePath))
// the generated "samples" from it does not work properly with the library.
InputStream is = getResources().openRawResource(R.raw.jinglebells);
byte[] data;
try {
data = IOUtils.toByteArray(is);
} finally {
if (is != null) {
is.close();
}
}
ShortBuffer sb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
short[] samples = new short[sb.limit()];
sb.get(samples);
return samples;
}
The sound file that I would like to get processed and pass to that library is created by a MediaRecorder with the following configurations
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
Basically that library requires PCM samples. Using that 3gp FileInputStream generated by MediaRecorder directly is not gonna cut it.
What I did is to use MediaExtractor and MediaCodec to convert the 3gp audio data into PCM samples by samples. and then it is fed into that library. Then everything worked =)
The logic in encoding audio data can be almost directly taken from here this awesome github repo

How to play a zipped wave file in Flash Mobile

I am working on a project in Flash Mobile using ActionScript. I have a zipped wav file that I need to be able to de serialize and play as needed in a Button Press action. Below is the code for zipping the wav file.
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
btnRecord.setStyle("icon", recOff);
sampleCount++;
// save the raw PCM samples as a bare WAV file
var wav:ByteArray = new ByteArray();
var writer:WAVWriter = new WAVWriter();
writer.numOfChannels = 1;
writer.sampleBitRate = 16;
writer.samplingRate = 11025;
samples.position = 0;
writer.processSamples(wav, samples, 11025, 1);
wav.position = 0;
// zip the WAV file
var fzip:FZip = new FZip();
fzip.addFile(name + sampleCount.toString(), wav);
var zip:ByteArray = new ByteArray();
fzip.serialize(zip);
var recSpot:Object = {
id: null,
audio: zip,
name: "New Audio File " + newRecNum,
existsdb: "false"
};
newRecNum++;
recordings.addItem(recSpot);
}
What can I do to play this file, really haven't had to play a zipped file before.
I'm not familiar with WAVWriter (which is probably somewhat beside the point), but here's what I do know.
Firstly, because of the nature of a compression, you cannot (as far as I know) play a zipped audio file, period. You will need to unzip it first.
A quick Google search turned up THIS AS3 TUTORIAL on unzipping with FZIP. The example program is using .PNGs, but I would assume you can adjust it to work with the raw .WAV file you zipped earlier. Skip down to Step 5 for the actual code. (You'll need to rewrite it to work with your interface, obviously.)
You won't need the DataProvider variable in step 5, as that is for components, specifically. You'll need to load your data into something else. If your method of playing WAV files is anything like mine (I use the as3WAVSound class), you'll probably want to load the data into a ByteArray and play off of that.
You also probably won't need the for loop he uses in step 10, as your code appears to be creating a ZIP with only one WAV file. That simplifies things considerably.
Anyway, I hope that answers your question!

How to merge two mp3 files into one (combine/join)

Can any tell how to combine/merge two media files into one ?
i found a topics about audioInputStream but now it's not supported in android, and all code for java .
And on StackOverflow i found this link here
but there i can't find solution - these links only on streaming audio . Any one can tell me ?
P.S and why i can't start bounty ?:(
import java.io.*;
public class TwoFiles
{
public static void main(String args[]) throws IOException
{
FileInputStream fistream1 = new FileInputStream("C:\\Temp\\1.mp3"); // first source file
FileInputStream fistream2 = new FileInputStream("C:\\Temp\\2.mp3");//second source file
SequenceInputStream sistream = new SequenceInputStream(fistream1, fistream2);
FileOutputStream fostream = new FileOutputStream("C:\\Temp\\final.mp3");//destinationfile
int temp;
while( ( temp = sistream.read() ) != -1)
{
// System.out.print( (char) temp ); // to print at DOS prompt
fostream.write(temp); // to write to file
}
fostream.close();
sistream.close();
fistream1.close();
fistream2.close();
}
}
Consider two cases for .mp3 files:
Files with same sampling frequency and number of channels
In this case, we can just append the second file to end of first file. This can be achieved using File classes available on Android.
Files with different sampling frequency or number of channels.
In this case, one of the clips has to be re-encoded to ensure both files have same sampling frequency and number of channels. To do this, we would need to decode MP3, get PCM samples,process it to change sampling frequency and then re-encode to MP3. From what I know, android does not have transcode or reencode APIs. One option is to use external library like lame/FFMPEG via JNI for re-encode.

Read ID3 Tags of an MP3 file

I am trying to read ID3 from a mp3 file thats locally stored in the SD card.
I want to basically fetch
Title
Artist
Album
Track Length
Album Art
You can get all of this using MediaMetadataRetriever
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(filePath);
String albumName =
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
Check the MP3 file format. Basically, you have to read the last 128 bytes of the file; if the first 3 bytes are "TAG", carry on and read the fields you need; if not, the file doesn't have the info attached.
if the last 128 byte begins with the token "TAG" the file has an ID3v1 (or ID3v1.1) tag.
ID3v2.3 tags are located in the beginning of the file (suitable for streaming) indicated by the token "id3". I believe ID3v2.4 is indicated by "3DE", but i'm not sure...

Determining audioformat of audio files in Android

Is there a way to determine the audio format of an audio file in Android? On normal java I do it like this:
File file= new File(...);
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format= stream.getFormat();
android.media.AudioTrack[1] has the following methods to access information about audio data:
getChannelCount to determine the number of channels
getChannelConfiguration to determine if you deal with mono or stereo content
getSampleRate to find out the sampling frequency
and
getAudioFormat to determine if you deal with 8bit or 16bit sample width.
The AudioTrack.getXXX methods you list merely return the values supplied to the constructor. This doesn't solve the original poster's issue.

Categories

Resources