I've recently added sounds into my LibGDX game. It's set up so that all the sounds I need are loaded into an AssetManager, and I retrieve them when I need to play them from a getSound(String name) method.
It works fine for a little bit when you play, but eventually it stops playing some, and sometimes most of them. I'd be fine with prioritizing the ones that are most recently played, and stopping the ones that are older if need be, but LibGDX doesn't seem to give you that much control over them.
The log error I get when this happens
E/AudioTrack: AudioFlinger could not create track, status: -12
E/SoundPool: Error creating AudioTrack.
It's usually playing quite a few at one time, probably around 10-20 small sounds at one time, depending on the situation, so I'm pretty sure that's the problem. I've read here about releasing a sound once it's played using a SoundPool, but I'm not entirely sure how to do that with LibGDX, or if it's possible, because I didn't see a class like that when I looked.
Also, I'm using ogg files for all of the sounds and none of them are very big.
Thanks!
Solved! By creating my own (kind of pseudo) Sound class, and a loader for it to be used with an AssetManager using assetManager.setLoader(). In the custom Sound class, I set every sound to keep track of their soundIds in an Array<Long>, then every time it plays I check the size of the array against a limit variable, stopping the oldest sound in the array. 0 meaning only able to be played one at a time, up to as far as I decide is necessary. This might not be a perfect solution, but it seems to work fairly well.
Criticism is welcome.
My created "Sound" class:
public class MySound {
private Sound sound;
private Array<Long> ids;
private int limit;
public MySound(Sound sound) {
this.sound = sound;
ids = new Array<Long>();
limit = 0;
}
public long play() {
limitSounds();
long id = sound.play();
ids.add(id);
return id;
}
public long play(float volume) {
limitSounds();
long id = sound.play(volume);
ids.add(id);
return id;
}
public long play(float volume, float pitch, float pan) {
limitSounds();
long id = sound.play(volume, pitch, pan);
ids.add(id);
return id;
}
public long loop() {
limitSounds();
long id = sound.loop();
ids.add(id);
return id;
}
public long loop(float volume) {
limitSounds();
long id = sound.loop(volume);
ids.add(id);
return id;
}
public long loop(float volume, float pitch, float pan) {
limitSounds();
long id = sound.loop(volume, pitch, pan);
ids.add(id);
return id;
}
public void stop() {
ids.clear();
sound.stop();
}
public void pause() {
sound.pause();
}
public void resume() {
sound.resume();
}
public void dispose() {
sound.dispose();
}
public void stop(long soundId) {
if (ids.contains(soundId, true)) {
ids.removeValue(soundId, true);
}
sound.stop(soundId);
}
public void pause(long soundId) {
sound.pause(soundId);
}
public void resume(long soundId) {
sound.resume(soundId);
}
public void setLooping(long soundId, boolean looping) {
sound.setLooping(soundId, looping);
}
public void setPitch(long soundId, float pitch) {
sound.setPitch(soundId, pitch);
}
public void setVolume(long soundId, float volume) {
sound.setVolume(soundId, volume);
}
public void setPan(long soundId, float pan, float volume) {
sound.setPan(soundId, pan, volume);
}
private void limitSounds () {
if (ids.size > limit) {
sound.stop(ids.get(0));
ids.removeIndex(0);
}
}
public void setLimit (int limit) {
this.limit = limit;
}
}
MySoundLoader class, for AssetManager:
public class MySoundLoader extends AsynchronousAssetLoader<MySound, MySoundLoader.SoundParameter> {
private MySound sound;
public MySoundLoader(FileHandleResolver resolver) {
super(resolver);
}
#Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, SoundParameter parameter) {
return null;
}
#Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
sound = new MySound(Gdx.audio.newSound(file));
}
#Override
public MySound loadSync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
MySound sound = this.sound;
this.sound = null;
return sound;
}
static public class SoundParameter extends AssetLoaderParameters<MySound> {
}
}
Related
This Is Main Fragment
Fragment:
private void getStock() {
dialog.show();
Retrofit retrofit = RetrofitClient.getRetrofitInstance();
apiInterface api = retrofit.create(apiInterface.class);
Call<List<Blocks>>call = api.getVaccineBlocks();
call.enqueue(new Callback<List<Blocks>>() {
#Override
public void onResponse(Call<List<Blocks>>call, Response<List<Blocks>> response) {
if (response.code() == 200) {
block = response.body();
spinnerada();
dialog.cancel();
}else{
dialog.cancel();
}
}
#Override
public void onFailure(Call<List<Blocks>> call, Throwable t) {
dialog.cancel();
}
});
}
private void spinnerada() {
String[] s = new String[block.size()];
for (int i = 0; i < block.size(); i++) {
s[i] = block.get(i).getBlockName();
final ArrayAdapter a = new ArrayAdapter(getContext(), android.R.layout.simple_spinner_item, s);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
spinner.setAdapter(a);
}
}
This Is Blocks Model
model:
package com.smmtn.book.models;
import java.io.Serializable;
public class Blocks implements Serializable {
public String id;
public String blockName;
public String blockSlug;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBlockName() {
return blockName;
}
public void setBlockName(String blockName) {
this.blockName = blockName;
}
public String getBlockSlug() {
return blockSlug;
}
public void setBlockSlug(String blockSlug) {
this.blockSlug = blockSlug;
}
}
here i need onitemclick with blockslug please any one can help, am new to android so i need some example.when on click i want take blockslug and load another method with that blockslug,like will get data from u "http://example.com/block/"+blockslug
i want to get blockslug from selected block
i hope guys i will get help
and sorry for my bad English,
First of all, you need to implement setOnItemSelectedListener. Refer to this https://stackoverflow.com/a/20151596/9346054
Once you selected the item, you can call them by making a new method. Example like below
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"OnItemSelectedListener : " + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_SHORT).show();
final String itemSelected = parent.getItemAtPosition(pos).toString();
showBlockSlug(itemSelected);
}
And then, at the method showBlockSlug() , you can call Retrofit.
private void showBlockSlug(final String blockslug){
final String url = "http://example.com/block/"+ blockslug;
//Do your stuff...
}
I am trying to range beacons and I am doing exactly what it is written here:
http://altbeacon.github.io/android-beacon-library/samples.html
didRangeBeaconsInRegion method is firing but always with empty collection.
I have installed "locate" by altbeacon and it located 3 beacons.
this is my code: am I missing something?
public class BeaconSingletone implements BeaconConsumer {
private static BeaconSingletone instance;
private final org.altbeacon.beacon.BeaconManager beaconManager2;
private ArrayList<BeaconThin> listNearBeacons = new ArrayList<>();
BeaconRegion region = new BeaconRegion("ranged region",
UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
private List<EventInterface> listeners = new ArrayList<EventInterface>();
private BeaconSingletone()
{
beaconManager2 = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(ar_activity.get());
// To detect proprietary beacons, you must add a line like below corresponding to your beacon
// type. Do a web search for "setBeaconLayout" to get the proper expression.
beaconManager2.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager2.bind(this);
public static BeaconSingletone getInstance() {
if(instance == null) {
instance = new BeaconSingletone();
}
return instance;
}
private void showNotification(Region region, final List<Beacon> list) {
listNearBeacons.clear();
listNearBeacons.add(new BeaconThin(3514,7580,-1));
for (Iterator<EventInterface> i = listeners.iterator(); i.hasNext(); ) {
EventInterface item = i.next();
//item.NewBeaconFound(list.get(0).getMajor(),list.get(0).getMinor(),Utils.computeAccuracy(list.get(0)));
item.NewBeaconsFound(listNearBeacons);
}
return;
}
#Override
public void onBeaconServiceConnect() {
beaconManager2.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<org.altbeacon.beacon.Beacon> beacons, org.altbeacon.beacon.Region region) {
if (beacons.size() > 0) {
Log.i("BeaconManager", "The first beacon I see is about "+beacons.iterator().next().getDistance()+" meters away.");
}
}
});
try {
beaconManager2.startRangingBeaconsInRegion(new org.altbeacon.beacon.Region("mybeacons", null, null, null));
} catch (RemoteException e) { }{
}
}
#Override
public Context getApplicationContext() {
return ar_activity.get();
}
#Override
public void unbindService(ServiceConnection serviceConnection) {
ar_activity.get().unbindService(serviceConnection);
}
#Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
return ar_activity.get().bindService(intent, serviceConnection, i);
}
}
You need to add a beacon layout for the beacon type you are using (iBeacon?). Replace this line:
beaconManager2.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
With the proper layout from here:
https://beaconlayout.wordpress.com
I've installed the PocketSphinx demo and it works fine under Ubuntu and Eclipse, but despite trying I can't work out how I would add recognition of multiple words.
All I want is for the code to recognize single words, which I can then switch() within the code, e.g. "up", "down", "left", "right". I don't want to recognize sentences, just single words.
Any help on this would be grateful. I have spotted other users' having similar problems but nobody knows the answer so far.
One thing which is baffling me is why do we need to use the "wakeup" constant at all?
private static final String KWS_SEARCH = "wakeup";
private static final String KEYPHRASE = "oh mighty computer";
.
.
.
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
What has wakeup got to do with anything?
I have made some progress (?) : Using addGrammarSearch I am able to use a .gram file to list my words, e.g. up,down,left,right,forwards,backwards, which seems to work well if all I say are those particular words. However, any other words will cause the system to match what is said to the "nearest" word from those stated. Ideally I don't want recognition to occur if words spoken are not in the .gram file...
Thanks to Nikolay's tip (see his answer above), I have developed the following code which works fine, and does not recognize words unless they're on the list. You can copy and paste this directly over the main class in the PocketSphinxDemo code:
public class PocketSphinxActivity extends Activity implements RecognitionListener
{
private static final String DIGITS_SEARCH = "digits";
private SpeechRecognizer recognizer;
#Override
public void onCreate(Bundle state)
{
super.onCreate(state);
setContentView(R.layout.main);
((TextView) findViewById(R.id.caption_text)).setText("Preparing the recognizer");
try
{
Assets assets = new Assets(PocketSphinxActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
}
catch (IOException e)
{
// oops
}
((TextView) findViewById(R.id.caption_text)).setText("Say up, down, left, right, forwards, backwards");
reset();
}
#Override
public void onPartialResult(Hypothesis hypothesis)
{
}
#Override
public void onResult(Hypothesis hypothesis)
{
((TextView) findViewById(R.id.result_text)).setText("");
if (hypothesis != null)
{
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBeginningOfSpeech()
{
}
#Override
public void onEndOfSpeech()
{
reset();
}
private void setupRecognizer(File assetsDir)
{
File modelsDir = new File(assetsDir, "models");
recognizer = defaultSetup().setAcousticModel(new File(modelsDir, "hmm/en-us-semi"))
.setDictionary(new File(modelsDir, "dict/cmu07a.dic"))
.setRawLogDir(assetsDir).setKeywordThreshold(1e-20f)
.getRecognizer();
recognizer.addListener(this);
File digitsGrammar = new File(modelsDir, "grammar/digits.gram");
recognizer.addKeywordSearch(DIGITS_SEARCH, digitsGrammar);
}
private void reset()
{
recognizer.stop();
recognizer.startListening(DIGITS_SEARCH);
}
}
Your digits.gram file should be something like:
up /1e-1/
down /1e-1/
left /1e-1/
right /1e-1/
forwards /1e-1/
backwards /1e-1/
You should experiment with the thresholds within the double slashes // for performance, where 1e-1 represents 0.1 (I think). I think the maximum is 1.0.
And it's 5.30pm so I can stop working now. Result.
you can use addKeywordSearch which uses to file with keyphrases. One phrase per line with threshold for each phrase in //, for example
up /1.0/
down /1.0/
left /1.0/
right /1.0/
forwards /1e-1/
Threshold must be selected to avoid false alarms.
Working on updating Antinous amendment to the PocketSphinx demo to allow it to run on Android Studio. This is what I have so far,
//Note: change MainActivity to PocketSphinxActivity for demo use...
public class MainActivity extends Activity implements RecognitionListener {
private static final String DIGITS_SEARCH = "digits";
private SpeechRecognizer recognizer;
/* Used to handle permission request */
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
((TextView) findViewById(R.id.caption_text))
.setText("Preparing the recognizer");
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(MainActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) findViewById(R.id.caption_text))
.setText("Failed to init recognizer " + result);
} else {
reset();
}
}
}.execute();
((TextView) findViewById(R.id.caption_text)).setText("Say one, two, three, four, five, six...");
}
/**
* In partial result we get quick updates about current hypothesis. In
* keyword spotting mode we can react here, in other modes we need to wait
* for final result in onResult.
*/
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null) {
return;
} else if (hypothesis != null) {
if (recognizer != null) {
//recognizer.rapidSphinxPartialResult(hypothesis.getHypstr());
String text = hypothesis.getHypstr();
if (text.equals(DIGITS_SEARCH)) {
recognizer.cancel();
performAction();
recognizer.startListening(DIGITS_SEARCH);
}else{
//Toast.makeText(getApplicationContext(),"Partial result = " +text,Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
public void onResult(Hypothesis hypothesis) {
((TextView) findViewById(R.id.result_text)).setText("");
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), "Hypothesis" +text, Toast.LENGTH_SHORT).show();
}else if(hypothesis == null){
makeText(getApplicationContext(), "hypothesis = null", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onDestroy() {
super.onDestroy();
recognizer.cancel();
recognizer.shutdown();
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onEndOfSpeech() {
reset();
}
#Override
public void onTimeout() {
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// .setRawLogDir(assetsDir).setKeywordThreshold(1e-20f)
.getRecognizer();
recognizer.addListener(this);
File digitsGrammar = new File(assetsDir, "digits.gram");
recognizer.addKeywordSearch(DIGITS_SEARCH, digitsGrammar);
}
private void reset(){
recognizer.stop();
recognizer.startListening(DIGITS_SEARCH);
}
#Override
public void onError(Exception error) {
((TextView) findViewById(R.id.caption_text)).setText(error.getMessage());
}
public void performAction() {
// do here whatever you want
makeText(getApplicationContext(), "performAction done... ", Toast.LENGTH_SHORT).show();
}
}
Caveat emptor: this is a work in progress. Check back later. Suggestions would be appreciated.
I am working on a game in C#.
I have a list of events, that can happen. E.g
List<Event> _events = new List<Event>();
_events.Add(new Event("A goblin approaches", 2));
_events.Add(new Event("A gang of thieves approaches", 3));
_events.Add(new Event("Some money has been stolen", 3));
_events.Add(new Event("Three goblins approach", 4));
_events.Add(new Event("A guard dies of unknown causes",4));
The string in the Event constructor is the event name and the number is the difficulty.
I was wondering if I could also add code into the constructor that can be run later on if the event is called. I'd like different code in each event.
Something like
_events.Add(new Event("Some money has been stolen", 3, "Supply.Gold = Supply.Gold -50"));
_events[2].runcode
I hope this makes sense, thanks
With this approach you can create events with simple implementation. And also difficult events with a lot of code (by extending Event class).
public class EventContext
{
public int Gold { get; set; }
}
public interface IEvent
{
void Do(EventContext context);
}
public abstract class Event : IEvent
{
protected Event(string title, int difficulty)
{
Title = title;
Difficulty = difficulty;
}
public string Title { get; private set; }
public int Difficulty { get; private set; }
public abstract void Do(EventContext context);
}
public class SimpleEvent : Event
{
private readonly Action<EventContext> _callback;
public SimpleEvent(string title, int difficulty, Action<EventContext> callback)
: base(title, difficulty)
{
_callback = callback;
}
public override void Do(EventContext context)
{
_callback(context);
}
}
internal class Program
{
private static void Main(string[] args)
{
var gameContext = new EventContext {Gold = 100};
var events = new List<IEvent>();
events.Add(new SimpleEvent("Some money has been stolen", 3, context => context.Gold -= 10));
events.First().Do(gameContext);
}
}
But I believe it can be better to separate event type and event handler.
Is it possible to get the value of phobe in-call volume from java me midlet? Changing of the volume is not necessary.
Thanks.
AFAIK,
It is not possible to access the phone volume. But you can set your application volume or get the application.
Sample code for Controlling the volume of your application :
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Ticker;
import javax.microedition.media.*;
public class VolumeControlDemo extends MIDlet implements CommandListener {
private Display display;
private Command exit,incr,decr;
Form frm;
VolumeControl vc;
int vol;
Player player;
public VolumeControlDemo() {
display = Display.getDisplay(this);
}
public void startApp() {
frm=new Form("VolumeControlDemo Demo");
exit= new Command("Exit",Command.EXIT,1);
decr= new Command("Decrease",Command.EXIT,1);
incr= new Command("Increase",Command.EXIT,1);
frm.addCommand(exit);
frm.addCommand(decr);
frm.addCommand(incr);
frm.setCommandListener(this);
display.setCurrent(frm);
try {
// Creating player object
player = Manager.createPlayer("/demo.wav");
// Setting loop count
player.setLoopCount(-1);
// Start sound
player.start();
Control cs[];
// Getting Controls object
cs = player.getControls();
for (int i = 0; i < cs.length; i++) {
if (cs[i] instanceof VolumeControl)
// Getting volume control
vc=(VolumeControl)cs[i];
}
} catch (Exception e) {}
}
public void pauseApp() {
}
public void destroyApp(boolean un) {
}
public void commandAction(Command cmd,Displayable d) {
try {
if(decr) {
if(vol>0) vol--;
vc.setLevel(vol);
} else if() {
if(vol<99) vol--;
vc.setLevel(vol);
}
frm.appent("vol="+vc.getLevel());
}catch(Exception e){}
}
}