How to perform animation according to sound level? - android

I have created a project where users voice get replicated http://androidsourcecode.blogspot.in/2013/07/android-audio-demo-audiotrack.html
and I want to perform animation according to voice level, I got to know about voice level through this tutorial http://www.doepiccoding.com/blog/?p=195#comment-45
now I want to integrate both of this code so that at certain voice level animation should get played at the same time animation should played ...
I am stuck here since long time...
I am calling a animation method at the time of writing track and that animation perform all the time which I don't want.
Please help me in this

So Finally I got the solution:
animpo.speak(i_Ravan);
while (isRecording) {
double lastLevel =1;
num = record.read(lin, 0, 2160);
double sumLevel = 0;
for (int i=0;i<num;i++){
sumLevel += lin[i];
}
lastLevel = Math.abs((sumLevel/num));
String ll = String.valueOf(lastLevel);
track.write(lin, 0, num);
Log.d("LastLevel",ll);
if(lastLevel > 5){
ClassA.speak(image); //Method which perform animation
}
}

Related

Is there any way to extract all the frames of a video in android studio?

I am working on an application in which i'm extracting all the frames of a video. I have tried multiple approaches but not able to get any results. So can anyone suggest how to do this?
I have tried OpenCV and MediaMetadataRetriever in android studio.
Simple answer is Yes !, you can do that easily using FmpegMediaMetadataRetriever library.
Add those two lines in your build.graddle under module app:
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.19'
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever native:1.0.19'
Sync your project.
Usage:
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
mmr.setDataSource(mUri);
mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ALBUM);
mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ARTIST;
// duration of the video
String time = retriever.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION);
int duration = Integer.parseInt(time);
//frame every selected period
int period = 1000000//each 1 second will get 1 frame, if you want more precision, minimise the period
int len = duration/period;
List<Bitmap> frames = ArrayList();
for(int i = 0; i<len; i++){
Bitmap frame = mmr.getFrameAtTime(i * period, FFmpegMediaMetadataRetriever.OPTION_CLOSEST); // frame at 2 seconds
frames.add(frame);
}
mmr.release();
//here you can do what ever you want from the frames arraylist
for(Bitmap frame: frames){
//here you can do what ever you want from the frame
}

Android Random Number Generator Hangs

I'm writing a very simple program. What I want is a 50/50 chance and display option A or option B.
Here is my code:
int min = 0;
int max = 100;
int randomValue;
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
btn_50_50.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (randomValue < 50) {
// do something
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
} else if (randomValue > 50) {
// do something else
randomValue = ThreadLocalRandom.current().nextInt(min, max + 1);
}
}
});
It works but if i press the button many times, especially if I kind of spam it, it stops working and only displays the last generated option.
I checked with a Toast message and it seems that it stops generating new numbers. It happens both in emulator and on a real device.
I have also tried importing java.util.Random and using that but exactly the same results.
Is there any better way to do this or a way to force the RNG to restart?
What happens when randomValue is exactly 50? :)
It's a 1 in 100 chance but it's bound to happen at some point.
Also, a 50/50 chance is the same as having 2 options and the chance of it being one of the options.
For example rolling (0,1) and checking if it's 0:
boolean isRandomChance = random.nextInt(0, 2) == 0;
Or, just the built in random boolean generator (true/false):
boolean isRandomChance = random.nextBoolean();

How to make a realtime rollingwindow graph using MPAndroidChart

[also posted on MPAndroidChart's Github]
I need realtime graph with a rolling windows, that's when I ran into 'problems'. Adding data is no problem, but after adding data with an Xvalue(index) that's higher than the current width of the graph the graph doesn't autoscroll because it don't seem to be able to always display [X] Xvalues.
Example of issue:
The result in graph 3 is not what I want for displaying realtime data. A scrollingwindow is much more usefull. So I tried to archieve this..
My working 'solution' was to remove the first Xvalue, add a new one and move all Xindexes of all Entries on screen one to the left. The result is some code like this:
int GRAPH_WIDTH = 10;
LineData lineData = chart.getData();
LineDataSet lineDataSet = lineData.getDataSetByIndex(0);
int count = lineDataSet.getEntryCount();
// Make rolling window
if (lineData.getXValCount() <= count) {
// Remove/Add XVal
lineData.getXVals().add("" + count);
lineData.getXVals().remove(0);
// Move all entries 1 to the left..
for (int i=0; i < count; i++) {
Entry e = lineDataSet.getEntryForXIndex(i);
if (e==null) continue;
e.setXIndex(e.getXIndex() - 1);
}
// Set correct index to add value
count = GRAPH_WIDTH;
}
// Add new value
lineData.addEntry(new Entry([random value], count), 0);
// Make sure to draw
chart.notifyDataSetChanged();
chart.invalidate();
This works quite well actually (as seen in this video here ), but I feel like there must be an easier way to do this. Maybe I overlooked some API window/scrolling..
But if this is the 'right' way to archieve this result then it would be an enhancement to add support for this kind of graphs in your library.
Thank you for the video.
I am surprised you found a workaround that is rather complicated but works quite well.
Unfortunately this is currently the only way to achieve what you want. I will work on making this easier soon probably reusing some of your code.
Also take a look at these two methods:
setScaleMinima(...)
centerViewPort(...)
I took your code and changed it a bit. It will only show up to GRAPH_WIDTH number of points at a time. Then it scrolls along deleting the older data. Useful if you're only interested in relatively recent data. Is that what you were going for?
public void addTimeEntry() {
String entry_date_time = new SimpleDateFormat("MMM d - HH:mm:ss").format(new Date());
LineData lineData = mChart.getData();
int GRAPH_WIDTH = 15;
if (lineData != null) {
LineDataSet set = lineData.getDataSetByIndex(0);
if (set == null) {
set = createSet();
lineData.addDataSet(set);
}
// Make rolling window
if (lineData.getXValCount() > GRAPH_WIDTH) {
lineData.getXVals().remove(0);
set.removeEntry(0);
lineData.getXVals().add(entry_date_time);
lineData.addEntry(new Entry((float) (Math.random() * 40) + 30f, GRAPH_WIDTH), 0);
// lineData.getXVals().add(entry_date_time);
// Move all entries 1 to the left..
for (int i=0; i < set.getEntryCount(); i++) {
Entry e = set.getEntryForXIndex(i);
if (e==null) continue;
e.setXIndex(e.getXIndex() - 1);
}
}
else{
lineData.getXVals().add(entry_date_time);
lineData.addEntry(new Entry((float) (Math.random() * 40) + 30f, lineData.getXValCount()-1), 0);
}
// let the chart know it's data has changed
mChart.notifyDataSetChanged();
mChart.invalidate();
}
}

Is my target selection AI efficient?

quick question. I am developing a top-down 2d Platformer game with lots of enemies in the map (at least a hundred spawn at the start of each level). Each enemy uses an AI that searches the map for objects with a specified tag, sorts each object into a list based on their distance, then reacts to the object closest to them.
My code works, but the thing is, if the machine my game is running on is slow, then my game lags. I want to be able to port my game to Android and iOS with low end specs.
In pursuit of putting less strain on the CPU, is there a better way to write my AI?
Here is my code:
void Start () {
FoodTargets = new List<Transform>(); // my list
SelectedTarget = null; // the target the enemy reacts to
myTransform = transform;
AddAllFood ();
}
public void AddAllFood()
{
GameObject[] Foods = GameObject.FindGameObjectsWithTag("Object");
foreach (GameObject enemy in Foods)
AddTarget (enemy.transform);
}
public void AddTarget(Transform enemy)
{
if (enemy.GetComponent<ClassRatingScript>().classrating != 1) { // classrating is an attribute each enemy has that determines their identity (like if they are a plant, a herbivore or a carnivore)
FoodTargets.Add (enemy); // adds the object to the list
}
}
private void SortTargetsByDistance() // this is how I sort according to distance, is this the fastest and most efficient way to do this?
{
FoodTargets.Sort (delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
private void TargetEnemy() // this is called every 4 frames
{
if (SelectedTarget == null) {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
else {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
}
if (optimizer <= 2) { // this is a variable that increments every frame and resets to 0 on the 3rd frame. Only every 3rd frame is the target enemy method is called.
optimizer++;
} else {
TargetEnemy ();
// the rest are attributes that the AI considers when reacting to their target
targetmass = SelectedTarget.GetComponent<MassScript> ().mass;
targetclass = SelectedTarget.GetComponent<ClassRatingScript> ().classrating;
mass = this.GetComponent<MassScript> ().mass;
classrating = this.GetComponent<ClassRatingScript> ().classrating;
distance = Vector3.Distance (transform.position, SelectedTarget.transform.position);
optimizer = 0;
}
Is there a more optimized way of doing this? Your help will be much appreciated. Thanks in advance!
I'm not awfully familiar with C# or Unity but I would look very carefully at what sorting algorithm your sorting method is using. If all you want is the closest Game Object, then sorting isn't necessary.
The fastest sorting algorithms, such as Quicksort, are O(n*log(n)). That is to say that the time it takes to sort a collection of n objects is bounded by some constant multiple of n*log(n). If you just want the k closest objects, where k << n, then you can perform k iterations of the Bubble Sort algorithm. This will have time-complexity O(k*n), which is much better then before.
However, if you only need the single closest object, then just find the closest object without sorting (pseudocode):
float smallestDistance = Inf;
object closestObject = null;
foreach object in objectsWithTag {
float d = distance(object, enemy);
if (d < smallestDistance) {
smallestDistance = d;
closestObject = object;
}
}
This extremely simple algorithm has time complexity O(n).

How to give pause or gap between words in TTS in android

I have given a text in mytts.speak("hi hello hi",parameter,parameter...);
But the words are continuously said without any gap or pause, I want to provide some time gap between words for more clarity.
How could I achieve this ?
If I understand your question correctly, this thread has the answer (by rushi).
Simply add a delay into the TTS queue by splitting the string and loop over the snippets via a for loop:
mytts.speak(snippet, QUEUE_ADD, null);
mytts.playSilentUtterance(2000, QUEUE_ADD, null);
Simply add a comma everywhere you want there to be pauses inserted.
For example: If you want the following web address to be said slower, enter it as a, t, t, r, s.gov
I realize this may not be suitable for some applications, but it definitely works.
This is how I put a longer pause between each word:
//initialize and declare TextToSpeech as tts
//"line" is the String you are trying to speak
char ch = '';
String temp = "";
for(int counter = 0; counter < line.length; counter++)
{
ch = charAt(counter);
temp = temp + ch;
if(ch == ' ' || counter == (line.length() - 1))
{
tts.speak(temp, TextToSpeech.QUE_ADD, null, null);
tts.playSilentUtterance(1000, TextToSpeech.QUEUE_ADD,null);
temp = "";
}
}
Try adding '/ / / / /' to your text. It should give you it some breathing room. If you want a longer pause, try adding more.
You can split you sentence in words and speak them in a for loop in a new thread. Splitting the phrase will give you a little delay, but if you want a longer one you could work on thread and make them wait.
It would be something like this:
final Handler h = new Handler();
String[] words = text.split(" ");
for (final CharSequence word : words) {
Runnable t = new Thread() {
#Override
public void run() {
m_TTS.speak(word, TextToSpeech.QUEUE_ADD, null, "TTS_ID");
}
};
h.postDelayed(t, 1000);
}

Categories

Resources