android


Generate audio graph from 3gpp


I'm writing audio recorder as part of application which has audio graph as well. For recording and showing live audio graph it was pretty easy, just call MediaRecorder.GetMaxAmplitude() every X ms and based on that update canvas which represents the audio graph.
The problem - I want to have same audio graph when one of the recording is opened, so now I can't use .GetMaxAmplitude() method since I would need to fully play the recording to generate the graph, which would take too much time and is just silly.
If recording output would be .wav, it would be pretty straightforward, lots of material out where how to do it, however MediaRecorder doesn't support .wav and I don't really want embed full ffmpeg with wrapper to my app just for this small functionality to decode 3gpp into wav.
What are my options here?
Using MediaExtractor and MediaCodec you can decode your 3gp (or any other supported mime type) into a series of PCM-16bit (mime audio/raw) buffers and from that you can subsample to obtain your desired amplitude graph at a "graphable" sampling rate.
This is an example using synchronous processing on the input/output buffer so run it on non-UI thread.
Synchronous PCM-16bit MediaCodec Example:
var file = new Java.IO.File(Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads), "someaudiofile.mp3");
if (file.CanRead())
{
var mediaExtractor = new MediaExtractor();
mediaExtractor.SetDataSource(file.ToString());
mediaExtractor.SelectTrack(0); // which track? lets assume single/mono for this example
var mediaFormat = mediaExtractor.GetTrackFormat(0);
var mime = mediaFormat.GetString(MediaFormat.KeyMime);
var mediaCodec = MediaCodec.CreateDecoderByType(mime);
mediaCodec.Configure(mediaFormat, null, null, MediaCodecConfigFlags.None);
mediaCodec.Start();
var bufferInfo = new MediaCodec.BufferInfo();
var inputDone = false;
while (true)
{
if (!inputDone) // process input stream and queue it up for output processing
{
int inputBufferIndex = mediaCodec.DequeueInputBuffer(10000);
if (inputBufferIndex >= 0)
{
var inputBuffer = mediaCodec.GetInputBuffer(inputBufferIndex);
int chunkSize = mediaExtractor.ReadSampleData(inputBuffer, 0);
Log.Debug("SO", $"Input Buffer: {inputBufferIndex}");
if (chunkSize <= 0)
{
mediaCodec.QueueInputBuffer(inputBufferIndex, 0, 0, 0L, MediaCodecBufferFlags.EndOfStream);
inputDone = true;
}
else
{
mediaCodec.QueueInputBuffer(inputBufferIndex, 0, chunkSize, mediaExtractor.SampleTime, MediaCodecBufferFlags.None);
mediaExtractor.Advance();
}
}
}
int outputBufferIndex = mediaCodec.DequeueOutputBuffer(bufferInfo, 1000000);
if (outputBufferIndex >= 0)
{
Log.Debug("SO", $"Output Buffer: {outputBufferIndex}");
if (bufferInfo.Size != 0)
{
var outputBuffer = mediaCodec.GetOutputBuffer(outputBufferIndex); // PCM 16-bit output
var outpuFormat = mediaCodec.GetOutputFormat(outputBufferIndex);
outputBuffer.Position(0);
// !!! Sub-sample the buffer based upon your needed sampling rate for display
var pcm16bitBuffer = outputBuffer.AsShortBuffer();
while (pcm16bitBuffer.HasRemaining)
{
var x = pcm16bitBuffer.Get();
// store the prior values and avg./max/... them for later display based upon some subsampling rate
}
pcm16bitBuffer.Dispose();
mediaCodec.ReleaseOutputBuffer(outputBufferIndex, false);
if (bufferInfo.Flags.HasFlag(MediaCodecBufferFlags.EndOfStream))
break;
}
else
break;
}
else if (outputBufferIndex == -2)
{
Log.Debug("SO", "Output buffer is not available yet, feed more input");
}
}
mediaCodec.Stop();
mediaCodec.Release();
}
Note: There are asynchronous methods available also, consult the MediaCodec docs for Android API levels for what is available for your app's targeted audience.
Output sample using the above method:
Re: MediaCodec

Related Links

Text selection in Android application using PhoneGap?
R.Java not generated
How to add data from custom list view from sqlite database?
setContentView and EditText
onLocationChanged is not called automatically
Android 4.0 kernel source code? [closed]
How do I access PreferenceFragment by id?
What are the Best Practices for Android Tools Locations?
I want to add the values of editText boxes over several layouts to post them to an editText box on a layout called results
Why can't I create a content resolver
Special chars are replaces with a square in android app
listview with two buttons and list row click
Phone call application
Why was our Application upgrade on Android Market not visible to all devices?
How to display a TableLayout with different column sizes in different rows in android programatically
android, Shared Library

Categories

HOME
static
jsf-2.2
entity-framework-core
tivoli
cq5
3d-reconstruction
pyqt4
settings
android-json
jtextpane
vert.x
opengl-3
spin
ibeacon-android
onedrive-api
bitnami
gruntfile
modbus-tcp
dimensional-modeling
feathersjs
git-extensions
identity-management
symfony-console
production
libigl
joptionpane
displaytag
comparator
ckfinder
data.stackexchange.com
maze
gpio
flooding
calculation
constexpr
boost-asio
kudu
weather
jmockit
turfjs
glib
classcastexception
jwplayer6
demo
opensmpp
c9.io
plaintext
levenshtein-distance
stylecop
phpdbg
fwrite
xbmc
linter
launchctl
twilio-click-to-call
reindex
pair-programming
semantic-logging
appdomain
oracleclient
truezip
headless
template-toolkit
cmp
universal-analytics
mathcad
filenet
restore
visual-studio-2008-sp1
slackware
flex-monkey
winusb
webjars
nikeplus-api
kango-framework
boost-serialization
highland.js
wso2greg
matlab-deployment
mraid
zxspectrum
xmltype
mass-assignment
linkedin-jsapi
ignite-ui
reflector
windows-embedded-standard
mt4j
ebay-lms
garbage
inkcanvas
wiimote
cgimage
agility.js
expression-blend-4
matlab-load
fsevents
winmain
ruby-1.8
squishit
ie-compatibility-mode
mathematical-notation
ifilter
httpcookie

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App