Giter Club home page Giter Club logo

audio-analyzer-for-android's Introduction

Audio Spectrum Analyzer for Android

A fork of Audio spectrum Analyzer for Android (See README.old for its original readme)

This software shows the frequency components' magnitude distribution (called spectrum) of the sound heard by your cell phone. Can be used to help tuning musical instrument or tone in singing, (tentative) measure environmental noise and sound revent education or experiments.

You can install this app through Google Play Store: Audio Spectrum Analyzer. Comments are welcome.

This software, Audio Spectrum Analyzer for Android, is released under the Apache License, Version 2.0.

Features

  • Show spectrum or spectrogram in real-time, with decent axis labels.
  • Linear, Logarithm and (Musical) Note frequency axis support.
  • You can put a cursor in the plot, for measurement or as a marker.
  • Easy gestures to fine exam the spectrum: i.e. pinch for scaling and swipe for view move.
  • Show peak frequency in a moderate accuracy (FFT + interpolation).
  • Show dB or A-weighting dB (dBA), although not suitable for serious application.
  • Possible to take averages of several spectrum then plot, make the spectrum smoother.
  • You may record the sound (while analyzing!) to a WAV file (PCM format). Then you can deal with it with your favorite tool.
  • Support all recorder sources except those need root privilege (see list in Android reference: MediaRecorder.AudioSource)
  • Support all possible sampling rates that your phone is capable. e.g. useful to find out the native (or best) sampling format for you phone.

Installation Requirements

  • Android version (API level)
    • >= Android 2.2 (API level 8), up-to app version v1.6.8.
    • >= Android 2.3 (API level 9), master branch, up-to year 2017.
    • >= Android 4.0 (API level 14), since year 2018.
    • These minimum version requirement is due to the "targetSdkVersion" and corresponding supported version range for library "com.android.support:support-v4".

Permissions:

  • Microphone, of course.
  • External storage (e.g MicroSD card), if you want to record the sound.

Development

git clone then open it use Android Studio. Install the SDK platform if requested (e.g. rev 116 needs API level 20), or tune the compileSdkVersion to the value that fits your needs.

(Notes on project import for old revision (rev <= 115))

Code structure

The whole program structure is roughly follows the MVC model:

AnalyzerActivity.java is the controler, as the main activity, it receives user inputs and system events, then sent corresponding commands to views or sampling and analyzing procedures.

AnalyzerViews.java is the view in MVC. It is used to manage (initialization, display, refresh) UI texts, buttons, dialogs and graphics. AnalyzerGraphic.java is a main sub-view which manage display of spectrum(SpectrumPlot.java) and spectrogram(SpectrogramPlot.java).

SamplingLoop.java is more or less the "model" part. It performs the sampling and FFT analysis, and inform the graphics update.

Processing of audio samples

The data process loop is located in run() in SamplingLoop.java (after commit c9e430b (Feb 06, 2017), but basicly this process didn't change since the initial commit), as well as the trigger of graphics refresh.

In every loop of while (isRunning), it reads a chunk of audio samples by

record.read(audioSamples, 0, readChunkSize);

, then "stream" it to STFT.java by

stft.feedData(audioSamples, numOfReadShort);

which calculates RMS and FFT whenever enough data is collected. The view is then informed through

activity.analyzerViews.update(spectrumDBcopy);

which ultimately calls invalidate() of the graphic view to request an update, then the AnalyzerGraphic.onDraw(Canvas c) will be called automatically.

Thanks

The code Audio spectrum Analyzer for Android gives me a good starting point, for learning Java and write this software (that I desired long ago).

audio-analyzer-for-android's People

Contributors

bewantbe avatar dsteve595 avatar nfsmaster208 avatar thinkingcow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

audio-analyzer-for-android's Issues

Got an initial error on the non-changed download

App is looking good. On a pure clone, I got this error. Any hints?

Error:Failed to crunch file C:\Users.....\audio-analyzer-for-android\audioSpectrumAnalyzer\build\intermediates\exploded-aar\com.android.support\appcompat-v7\25.3.0\res\drawable-hdpi-v4\abc_ic_menu_share_mtrl_alpha.png into C:\Users.... audio-analyzer-for-android\audioSpectrumAnalyzer\build\intermediates\res\merged\debug\drawable-hdpi-v4\abc_ic_menu_share_mtrl_alpha.png

Improve music note detection below 100Hz and

Hi. Thank you for giving this cool project to the community.

I have compiled it and used the app with my piano to see how note detection works. I've seen two problems.

  1. Notes below G2 (~98Hz) are not recognised.
  2. Often one note is mistaken for the same note one octave higher. For example Im pressing A3 on the keyboard and app says A4.

I'm thinking if note recognition could be improved. So A3 is not shown as A4 and few more low frequency notes are recognised. Can you suggest some improvement that I can do? I'm using stft.maxAmpFreq to see what note is it.

Datatype of Samples?

I am first trying to figure out exactly where and how the program is interpreting the datastream from the Android sources. I have been considering enabling the remote_submix Audio Source, but in any case, it would be helpful if you may be able to point me in the direction of where the program is taking in the data stream and basically the pipeline for which the data travels. The goal is to be able to load and analyze audio files. Thank you!

Ability to read audio file?

As per user request in Play Store it is good to have the ability to load recored files and show its spectrum/spectrogram.

There are several things need to be fixed:

  • Load the whole file or part of a file?

    1. The ability to load whole file would require tricky time zoom in/zoom out, and can be CPU and RAM intensive.
  • How to move along time? or maybe just play it in real time? Related to previous question.

  • Do we need loudspeaker play back?

Having all these features is of course good, but that can be too complex. It is better to solve the most wanted/useful part first.

@nfsmaster208

Spam(Spectrogram) Not working on Android Oreo.

For some reason the display of the spectrogram is not displaying the graphical data in an emulator and Google Pixel device running Android Oreo. All the data in that mode is working, just for some reason the rendering of the spectrogram is not happening. I tried to poke around the code, and I could not figure out what the issue is.

@bewantbe

Logarithmic frequency axis?

Hello
I see linear frequency axis only. It will be good to add logarithmic frequency axis or select between them.

A question about dB scale

Hello,

I am using your Audio Spectrum Analyser and really appreciate your work - it is awesome!

Nevertheles, I have a question about changing dB scale to linear - is it possible? Can you kindly tell me if there is any way to change the original code and make the app to show y-axis values in linear scale instead of dBs?

Thank you very much.

Yours sincerelly,
Filip

Publication on F-Droid

Hello, this app looks really great and there is no match for it on F-Droid, the repository for FLOSS android apps, with the same feature set right now. I would like to propose it for inclusion into F-Droid. Do you have any objections?

More window function

Add following window functions for your app, there are certain window and value is doing well in speech enhance from spectrogram even at high FFT size, like Gaussian b=8.0 and Flat-top, I also have this in my own Win32 API based spectrum analyzer:
case "Flat-top": {
for (int i=0; i<wnd.length; i++) {
double f = 6.283185307179586 * i / (wnd.length - 1);
wnd[i] = 1 - 1.93 * Math.cos(f) + 1.29 * Math.cos(2 * f) - 0.388 * Math.cos(3 * f) + 0.028 * Math.cos(4 * f);
}
break;
}
case "Nuttall": {
double a0 = 0.355768;
double a1 = 0.487396;
double a2 = 0.144232;
double a3 = 0.012604;
for (int i=0; i<wnd.length; i++)
{
double scale = 3.141592653589793 * i / (wnd.length - 1);
wnd[i] = a0 - a1 * Math.cos(2.0 * scale) + a2 * Math.cos(4.0 * scale) - a3 * Math.cos(6.0 * scale);
}
break;
}
case "Gaussian, b=3.0": {
double Beta = 3.0;
double Arg;
for (int i=0; i<wnd.length; i++) {
Arg = (Beta * (1.0 - ((double)i / (double)wnd.length) * 2.0));
wnd[i] = Math.exp(-0.5 * (Arg * Arg));
}
break;
}
case "Gaussian, b=5.0": {
double Beta = 5.0;
double Arg;
for (int i=0; i<wnd.length; i++) {
Arg = (Beta * (1.0 - ((double)i / (double)wnd.length) * 2.0));
wnd[i] = Math.exp(-0.5 * (Arg * Arg));
}
break;
}
case "Gaussian, b=6.0": {
double Beta = 6.0;
double Arg;
for (int i=0; i<wnd.length; i++) {
Arg = (Beta * (1.0 - ((double)i / (double)wnd.length) * 2.0));
wnd[i] = Math.exp(-0.5 * (Arg * Arg));
}
break;
}
case "Gaussian, b=7.0": {
double Beta = 7.0;
double Arg;
for (int i=0; i<wnd.length; i++) {
Arg = (Beta * (1.0 - ((double)i / (double)wnd.length) * 2.0));
wnd[i] = Math.exp(-0.5 * (Arg * Arg));
}
break;
}
case "Gaussian, b=8.0": {
double Beta = 8.0;
double Arg;
for (int i=0; i<wnd.length; i++) {
Arg = (Beta * (1.0 - ((double)i / (double)wnd.length) * 2.0));
wnd[i] = Math.exp(-0.5 * (Arg * Arg));
}
break;
}

Errors in compilation after just open the project for first time

The Errors:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':audioSpectrumAnalyzer:mergeDebugResources'.7
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:100)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:60)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:626)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:581)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.android.build.gradle.tasks.ResourceException: Error: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details
at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:296)
at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:46)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
... 32 more
Caused by: Error: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details
at com.android.ide.common.res2.MergedResourceWriter.end(MergedResourceWriter.java:332)
at com.android.ide.common.res2.DataMerger.mergeData(DataMerger.java:301)
at com.android.ide.common.res2.ResourceMerger.mergeData(ResourceMerger.java:412)
at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:285)
... 48 more
Suppressed: java.lang.RuntimeException: Some file processing failed, see logs for details
at com.android.builder.internal.aapt.QueuedResourceProcessor.waitForAll(QueuedResourceProcessor.java:121)
at com.android.builder.internal.aapt.QueuedResourceProcessor.end(QueuedResourceProcessor.java:141)
at com.android.builder.internal.aapt.v2.QueueableAapt2.close(QueueableAapt2.java:104)
at com.android.build.gradle.tasks.MergeResources.doFullTaskAction(MergeResources.java:293)
... 48 more
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:503)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:462)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:79)
at com.android.ide.common.res2.MergedResourceWriter.end(MergedResourceWriter.java:327)
... 51 more
Caused by: java.util.concurrent.ExecutionException: com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details
at com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:503)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:462)
at com.google.common.util.concurrent.AbstractFuture$TrustedFuture.get(AbstractFuture.java:79)
at com.android.builder.internal.aapt.v2.QueueableAapt2.lambda$compile$0(QueueableAapt2.java:136)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
... 1 more
Caused by: com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details
at com.android.builder.png.AaptProcess$NotifierProcessOutput.handleOutput(AaptProcess.java:443)
at com.android.builder.png.AaptProcess$NotifierProcessOutput.err(AaptProcess.java:395)
at com.android.builder.png.AaptProcess$ProcessOutputFacade.err(AaptProcess.java:312)
at com.android.utils.GrabProcessOutput$1.run(GrabProcessOutput.java:104)

CalibrationLoad isnt found.

On the master branch, it seems needing "CalibrationLoad", but the code wouldnt be commited.

We could use the code base 1837ed9 on behalf of it, but itd be great if you update the master branch.

Possibility to add calibration function?

As per user request in Play Store, have the ability to calibrate the spectrum would be nice.

But:

  • Is there some standard (e.g. file format, procedure) for calibrating the mic?
  • Suppose the user have a reference mic, how to use that mic to calibrate the user's mobile device?
  • Is it possible for user to "calibrate" his/her mic without any extra equipment?

@nfsmaster208

License Information

Hi, your app is great. Can I use it in my own app that is published in PlayStore?

Incorrect display of peak frequencies

Hello,

Thank you for your wonderful program!
Unfortunately I faced inexplicable effect when using it.

In Android Studio I started your application (version 1.6.9). To demonstrate the effect at the same time, I launched Windows application Oscilloscope 2.51 in the FFT mode (screenshots are in the attached zip-file).

I connected the device (generator) to the microphone input of the computer (screenshot 1). As you can see, the view is very strange: the spectrum decreases approximately at a frequency of 3700-4000 Hz.

Then I began to increase the frequency of the signal (screenshot 2). Everything works fine (peak frequencies are very close) right up to a frequency of about 37xx Hz on which there is an incomprehensible effect (screenshot 3): please pay attention - peak values differ dramatically. Next (screenshot 4), the differences in peak frequencies become even greater.

Could you please explain me why this is happening? Maybe it's a bug in the application?

Thank you.

P.S.
Oscilloscope 2.51 displays the peak frequencies correctly.
screenshots.zip

How can I use raw PCM data directly as input?

I have an audio monitor hardware and I can get raw PCM data from it.
How can I use the data as fft plot input?
I'm checking the run() method in SamplingLoop.java file, is it the correct place that I can modify to use raw PCM data as input?

Adjustable dynamic range/white point in spectrogram

Some microphones are good in sound quality, but insensitive.
The audio that I observe gets colors from the low end of the Color map and it would be nice to be able to use the whole color map.

Can you please make a setting for Spectrogram "upper limit" or "white point"?

If the "View Range Setting" would apply to the colors of the Spectrogram that would be great as well.

How do I get FFT size of more than 32768?

By default it allows up to 16384 samples. If I edit audioSpectrumAnalyzer/src/main/res/values/arrays.xml, I can also get 32768 samples.

But if I try further values (65536, 131072), it stops working (shows empty 1D or 2D plot) if I select those values.

What else do I need to change to make it work for large windows?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.