How to let a sound play once in Processing? - java

import processing.serial.*;
import processing.sound.*;
SoundFile file;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
//String antwoord = "A";
void setup()
{
size(300,300);
// I know that the first port in the serial list on my mac
// is Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{ // If data is available,
val = trim( myPort.readStringUntil(ENTER) );
// read it and store it in val
}
//println(val); //print it out in the console
file = new SoundFile(this,"Promise.mp3");
if ("A".equals(val) == true && file.isPlaying() == false) {
file.play();
file.amp(0.2);}
else{
ellipse(40,40,40,40);
}
}
I got this code, but I want the sound to keep playing as long as the signal 'A' is given. Now it starts playing constantly, which leads to a weird static noise. How can I make it just play steadidly?

You're creating a new SoundFile in every run of draw. So file.isPlaying() will always return false. Only create a new SoundFile if you haven't already. The simplest solution is probably to move file = new SoundFile(this,"Promise.mp3"); into setup
Or you check or remember if you already loaded the file.

I am sorry if it is a bit disconnected but I recommend using minim or a different sound library instead of the processing one, since it causes a lot of problems in exporting (at least it had done so consistently for me).

Related

Why is GetExternalFileDirs not working in android?

I am working on a sample project in unity android where application reads a textfile in an OTG pen drive connected to the android phone, the problem is my code works fine in some devices but it doesn't work in some devices. I am unable to figure out the main cause even through the logcat extreme as it doesn't throw any error at all that specifies code error.
I tried adding text logs to print text in between the code to see which texts are not printed, which would further tell me that after which line code stopped working but all the texts are printed.
This is my code that detects the USB and returns true if a text file is present in USB:
public void LocateFile()
{
textfileData = null;
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
// Get all available external file directories (emulated and USBdrives)
AndroidJavaObject[] externalFilesDirectories = context.Call<AndroidJavaObject[]>("getExternalFilesDirs", (object)null);
AndroidJavaObject emulated = null;
AndroidJavaObject USBdrive = null;
for (int i = 0; i < externalFilesDirectories.Length; i++)
{
AndroidJavaObject directory = externalFilesDirectories[i];
using (AndroidJavaClass environment = new AndroidJavaClass("android.os.Environment"))
{
bool isRemovable = environment.CallStatic<bool>("isExternalStorageRemovable", directory);
bool isEmulated = environment.CallStatic<bool>("isExternalStorageEmulated", directory);
if (isEmulated)
{
emulated = directory;
}
else if (isRemovable && isEmulated == false)
{
USBdrive = directory;
}
}
}
// Return the USBdrive if available
if (USBdrive != null)
{
if (File.Exists(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt"))
{
textfileData = File.ReadAllText(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt");
}
}
}
}}
This code works on my android phone and returns true after detecting the file present in pendrive.
Can anyone tell me what could be the issue and point me in the right direction, I will greatly appreciate your support on this.
This locateFile() function is called on Update().
Update: I tried to debug the number of storage found in mobile and code is not reading the USB. It reads internal and SD storage perfectly.
Nokia 5 is the only phone the code has worked on so far but in 99% android devices GetExternalFilesDir is not reading usb storage.
Please someone tell me an alternate or how do I get this to work, it is very important.

Write multiple files with same string without hanging the UI

I am working on an Android App that changes the CPU Frequency when a foreground app changes. The frequencies for the foreground app is defined in my application itself. But while changing the frequencies my app has to open multiple system files and replace the frequency with my text. This makes my UI slow and when I change apps continuously, it makes the systemUI crash. What can I do to write these multiple files all together at the same time?
I have tried using ASynctaskLoader but that too crashes the SystemUI later.
public static boolean setFreq(String max_freq, String min_freq) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(max_freq.getBytes(Charset.forName("UTF-8")));
ByteArrayInputStream inputStream1 = new ByteArrayInputStream(min_freq.getBytes(Charset.forName("UTF-8")));
SuFileOutputStream outputStream;
SuFileOutputStream outputStream1;
try {
if (max_freq != null) {
int cpus = 0;
while (true) {
SuFile f = new SuFile(CPUActivity.MAX_FREQ_PATH.replace("cpu0", "cpu" + cpus));
SuFile f1 = new SuFile(CPUActivity.MIN_FREQ_PATH.replace("cpu0", "cpu" + cpus));
outputStream = new SuFileOutputStream(f);
outputStream1 = new SuFileOutputStream(f1);
ShellUtils.pump(inputStream, outputStream);
ShellUtils.pump(inputStream1, outputStream1);
if (!f.exists()) {
break;
}
cpus++;
}
}
} catch (Exception ex) {
}
return true;
}
I assume SuFile and SuFileOutputStream are your custom implementations extending Java File and FileOutputStream classes.
Couple of points need to be fixed first.
f.exists() check should be before initializing OutputStream, otherwise it will create the file before checking exists or not. This makes your while loop to become an infinite loop.
as #Daryll suggested, use the number of CPUs with while/for loop. I suggest using for loop.
close your streams after pump(..) method call.
If you want to keep the main thread free, then you can do something like this,
see this code segment:
public static void setFreq(final String max_freq, final String min_freq) {
new Thread(new Runnable() {
//Put all the stuff here
}).start();
}
This should solve your problem.
Determine the number of CPUs before hand and use that number in your loop rather than using a while (true) having to do SuFile.exists() every cycle.
I don't know what SuFileOutputStream is but you may need to close those file output streams or find a faster way to write the file if that implementation is too slow.

disable other sounds in java

I wrote a program in Java using the pi4j lib to make sound whenever a (physical) button is clicked. This program works, but it now plays all the sounds interchangeably. I want that when you click on 2,3,4 or more buttons you only hear one sound.
This is the code I hope you can help.
public class ButtonSoundsProject{
public static void main(String args[]) throws InterruptedException {
System.out.println("Toy has been started!");
// create gpio controller
final GpioController gpio = GpioFactory.getInstance();
// provision gpio pin #02 as an input pin with its internal pull down resistor enabled
GpioPinDigitalInput[] pins = {
gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN),};
final ArrayList<String> soundList = new ArrayList<String>();
soundList.add("/home/pi/Sounds/Sound1.wav");
soundList.add("/home/pi/Sounds/Sound2.wav");
soundList.add("/home/pi/Sounds/Sound3.wav");
soundList.add("/home/pi/Sounds/Sound4.wav");
soundList.add("/home/pi/Sounds/Sound5.wav");
soundList.add("/home/pi/Sounds/Sound6.wav");
soundList.add("/home/pi/Sounds/Sound7.wav");
soundList.add("/home/pi/Sounds/Sound8.wav");
soundList.add("/home/pi/Sounds/Sound9.wav");
soundList.add("/home/pi/Sounds/Sound10.wav");
soundList.add("/home/pi/Sounds/Sound11.wav");
soundList.add("/home/pi/Sounds/Sound12.wav");
// create and register gpio pin listener
GpioPinListenerDigital listener = new GpioPinListenerDigital() {
#Override
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// display pin state on console
final int randomNum = 0 + (int) (Math.random() * 12);
System.out.println(randomNum);
System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
InputStream in;
try {
System.out.println(soundList.get(randomNum).toString());
String filepath = soundList.get(randomNum).toString();
in = new FileInputStream(new File(filepath));
AudioStream as = new AudioStream(in);
AudioPlayer.player.start(as);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
gpio.addListener(listener, pins);
for (;;) {
Thread.sleep(500);
}
}
}
As stated in the comments, I can't give you advise regarding the AudioStream and AudioPlayer classes because I don't seem to have those in my JDK. Since my method is similar, I'll give you what I have, and you can hopefully take it from there.
Basically, the solution is to stop and/or "mute" that audio clip. This is how I accomplish it using the javax.sound package.:
private Clip currentAudioClip; // Keep a reference to the current clip being played
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// Call this every time regardless.
// If nothing is playing, this will do nothing.
stopAudio();
String filepath = soundList.get(randomNum)
URL soundFileUrl = new File(filePath).toURI().toURL();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFileUrl);
Line.Info lineInfo = new Line.Info(Clip.class);
Line line = AudioSystem.getLine(lineInfo);
currentAudioClip = (Clip) line;
currentAudioClip.open(audioInputStream);
audioClip.start();
// Alternative if you want to loop continuously. Comment out the `.start` line to use this.
// audioClip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stopAudio(){
if(audioClip != null){
muteLine(); // A gotcha I discovered (see explanation below)
audioClip.stop();
// audioClip.loop(0); // if you chose to loop, use this instead of `.stop()`
audioClip.flush();
audioClip = null;
}
}
public void muteLine(){
BooleanControl muteControl = (BooleanControl) audioClip.getControl(BooleanControl.Type.MUTE);
if(muteControl != null){
muteControl.setValue(true); // True to mute the line, false to unmute
}
}
In short, every time a pin state change event is fired, the previous audio clip will be ceased, and a new one should play. You shouldn't get any sound overlapping with this.
Also note that this is a slight modification of my original code, so let me know if there are any issues
Note about the GOTCHA
I wrote a question over on the Raspberry PI Stackexchange about an odd problem I encountered. The problem was that I discovered my audio clip would not cease playing on command. It would continue playing for a seemingly arbitrary amount of time. The stranger thing is that I only observed this while testing the app on the raspberry; it worked perfectly fine on my local machine (and even on several other machines).
It is possible my issue is related to the "looping" of my clip; if that is the case, and you simply want the clip to play for its length and no further, you may not encounter that issue, and you can probably dispense with the "muting" code I included. However, if you do observe the same issue, at least you have a solution.
Hope this helps, let me know if you have any questions.

JNetPcap in eclipse does not print error... Ubuntu 12.04

Have some problems with JNetPcap.
I uses Ubuntu 12.04, and trying to make packet snipper that based in java language.
What I did is below.
I have downloaded JNetPcap 1.3.0.
And as tutorial said built a java project.
http://jnetpcap.com/examples/dumper <- this is the link.
I typed just like that link and I got my first problem.
PcapHandler Class is deprecated. So I find the document and replace it with ByteBufferHandler.
Now I compile this project and got an unsatifiedLinked Error.
I have tried with static block to load that library.
After some attempts I copied "libjnetpcap.so" to /usr/lib/
now I remove unsatisfiedLinked Error. but somehow it stops in 1st Error check.
It prints "1st error check : ", then exit automatically.
public static void main(String[] args) {
List<PcapIf> alldevs = new ArrayList<PcapIf>();
StringBuilder errbuff = new StringBuilder();
int r = Pcap.findAllDevs(alldevs, errbuff);
//============1st check
if(r == Pcap.NOT_OK || alldevs.isEmpty()){
System.err.printf("1st error check : %s\n", errbuff.toString());
return;
}
PcapIf device = alldevs.get(1);
//===================== END
int snaplen = 64 * 1024;
int flags = Pcap.MODE_PROMISCUOUS;
int timeout = 10 * 1000;
Pcap pcap = Pcap.openLive(device.getName(),snaplen, flags, timeout, errbuff);
//============2nd check
if(pcap == null){
System.err.printf("2nd error check : %s\n", errbuff.toString());
return;
}
//===================== END
String ofile = "/home/juneyoungoh/tmp_capture_file.cap";
final PcapDumper dumper = pcap.dumpOpen(ofile);
ByteBufferHandler<PcapDumper> handler = new ByteBufferHandler<PcapDumper>() {
#Override
public void nextPacket(PcapHeader arg0, ByteBuffer arg1, PcapDumper arg2) {
dumper.dump(arg0, arg1);
}
};
pcap.loop(10,handler, dumper);
File file = new File(ofile);
System.out.printf("%s file has %d bytes in it!\n", ofile, file.length());
dumper.close();
pcap.close();
if(file.exists()){
file.delete();
}
}
if is there any good reference or wonderful idea, please share.
Thanks.
On Linux, a program will probably have to run as root, or with sufficient privileges granted in some other fashion, in order to be able to open any devices, and, currently, pcap_findalldevs(), which is presumably what the Pcap.findAllDevs method uses, tries to open each of the devices it finds, and only returns the devices it can open.
So you'll have to run your Java program as root, or will somehow have to arrange that it have sufficient privileges (CAP_NET_RAW and CAP_NET_ADMIN) to get a list of network adapters and open those adapters.

Correct using VLCj

I try to use VLCj to get access to web-cameras. I am using this code:
public static void main(String[] args) {
// Create player.
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
DirectMediaPlayer mediaPlayer = mediaPlayerFactory.newDirectMediaPlayer(
320, 240,
new RenderCallback() {
#Override
public void display(Memory arg0) {
// Do nothing.
}
});
// Options setup.
String[] options = new String[]{};
String mrl = "v4l2:///dev/video0"; // Linux
// Start preocessing.
mediaPlayer.startMedia(mrl, options);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop precessing.
mediaPlayer.stop();
mediaPlayer = null;
System.out.println("Finish!");
}
And this code partially works -- I can get and work with BufferedImage, but:
I got an error in to output: [0x7f0a4c001268] main vout display error: Failed to set on top
When main loop is finished and camera was disabled program don't finished! I see Finish! message, but program not return control into IDE or console.
UPD:
I am using openSUSE 12.2 x64, VLC 2.0.3 installed and working properly for all video files, library VLCj 2.1.0.
This code working properly:
public static void main(String[] args) {
// Configure player factory.
String[] VLC_ARGS = {
"--intf", "dummy", // no interface
"--vout", "dummy", // we don't want video (output)
"--no-audio", // we don't want audio (decoding)
"--no-video-title-show", // nor the filename displayed
"--no-stats", // no stats
"--no-sub-autodetect-file", // we don't want subtitles
"--no-inhibit", // we don't want interfaces
"--no-disable-screensaver", // we don't want interfaces
"--no-snapshot-preview", // no blending in dummy vout
};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(VLC_ARGS);
// Create player.
HeadlessMediaPlayer mediaPlayer = mediaPlayerFactory.newHeadlessMediaPlayer();
// Select input device.
String mrl = "v4l2:///dev/video0"; // Linux
// Start processing.
mediaPlayer.startMedia(mrl);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop processing.
mediaPlayer.stop();
// Finish program.
mediaPlayer.release();
mediaPlayerFactory.release();
}
Re your native window: VLCj opens a shared instance to the VLC library.
A headless media palyer is NOT intended to have a video or audio output!
In fact, if you need anything to play (and not to stream to anywhere else) you need to create either an output window or use a direct media player (may be much more complicated)
So, if a headless player needs to play something it opens a native window to perform the playback!
Source: http://www.capricasoftware.co.uk/wiki/index.php?title=Vlcj_Media_Players
Re the error: the video display component MUST be the top component of the panel, window or whereever it is added to. Otherwise it will throw the error
main vout display error: Failed to set on top
Furthermore, if you put anything over the component it will destroy the video output which won't work anymore!
Anyway, I don't know how the DirectMediaPlayer works in detail but VLCj has some weird behaviour... Maybe getSnapshot() needs a video display component but I'm not sure.
Re your not finishing program: you join to finish your own thread. This can't work because your thread "sleeps" until the other thread who is waited for has been terminated but as this is your own thread it "sleeps" and won't terminate.
You can test this behaviour with this short code in a main method:
System.out.println("Test start");
Thread.currentThread().join();
System.out.println("Test stop");
You will NEVER reach the "Test stop" statement.

Categories