Java stop MIDI playback - java

Hi I have java application which plays midi messages from sequence. I'm doing this using jfugue library.
the problem is when I'm tryingto stop playback with stop button (which call sequencer.stop() and sequencer.close()) the last played note is sound all of rest time, and I can't stop it.
So I'm asking about solution about stopping all audio and MIDI too! sound playback from java application.
Notice:
If you want propose just mute volume, you need to know that I want end-use will be able to press play button again and hear the sound again, so muting volumr will be not a solution, or explain please.
Thank you!

I'm guessing you need to call Player.allNotesOff() before calling sequencer.stop(). Untested, so please let me know if it didn't work.

When MIDI plays music, it uses a combination of NOTE_ON and NOTE_OFF events. It sounds like when you press the stop button, the sequence is stopping after a NOTE_ON event had been sent, but before a NOTE_OFF event was sent. That means the sound will continue to play indefinitely.
Player.allNotesOff() in JFugue makes a call to JavaSound's allNotesOff() method in the Channel class; this call is made for each MIDI Channel (there are 16 channels). It's unfortunate that this solution isn't working. Try calling Player.allNotesOff() after sequencer.stop(), see if that helps.

Related

MIDI Sequencer stop without flushing

For a project I am working on I need to pause the midi sequencer and I want all the sounding notes to sustain and thus make those notes endless. The problem I am facing is that sequencer.stop() apparently not only stops the playback, but also sends MIDI note off messages to all sounding notes, terminating all sounding notes (in some literature refered to as flushing).
I have tried to use sequencer.setTempoInBPM(0) and that gets the job done, but has other unwanted side-effects specific to my project.
The most obvious solution then seems overriding Sequencer.stop(), but how do I do that? And how exactly will that overridden method look like?
Edit:
I would like to edit the question in response to the comment of gpasch.
not only stops the playback, but also sends MIDI note off messages to
all sounding notes: what are you talking about?? isnt this the same
thing??
That is true for audio, but that is not true for MIDI. The MIDI protocol doesnt specify any audio data by itself. It only gives instructions to a musical instruments on what to play. The instrument interprets the MIDI messages and makes the final sound.
In order to let an instrument play a sound of one second, this are the actions:
[Sequencer] MIDI Message Out: note on
[Instrument] MIDI Message In: note on
[Instrument] Starts interpreting note on: starts producing sound
[Sequencer] Waits one second
[Sequencer] MIDI Message Out: note off
[Instrument] MIDI Message In: note off
[Instrument] Starts interpreting note off: stops producing sound
So, if this process gets interrupted on step 4, it would create an "endless note". Because the MIDI instrument got instructions to begin playing a certain note, but never got an instruction to stop playing that note. [*]
Looking back to my question. When I call sequencer.stop() in the middle of a note (step 4), instead of having an "endless note", all notes that are being played on that moment that did not yet have got an note off message, stop sounding. The logical explenation for that, is that sequencer.stop() sends a MIDI All Note Off message under the hood. We can be really thankfull for that, because otherwhise sequencer.stop() would be a real mess. In my particular case though I really need the sequencer to not send the note off message. So the question is: can I make a workaround for that?
*
If it is a piano sound with a natural decay of the sound, the sound will eventually die. But with a synth sound the sound will persist till there has been
The way I would do it is. Create a filter which would basically receive everything sent from the sequencer and send it to your midi out. Inside this filter create a condition where if the "pause flag" is true all note offs would be received but not sent.
Create a pause() method which when called first sets your "pause flag" to true and then does sequencer.stop().
Of course you would need some way to keep track of the note offs that have been blocked so that you can actually stop them when you eventually do want to or else they will really stay on for ever.

Executing code after MediaPlayer is done playing?

I was wondering I'm working on an Android app where MediaPlayer/TextToSpeech is used to tell the user something and then a Speech Recognition object opens up after the MediaPlayer/TextToSpeech finishes and another is played after they answer the question with the recognition. Problem is I'm not 100% sure of a way, or good way, to delay the Speech Recognition from opening right after MediaPlayer is starts, or waiting till mediaplayer is done before speech recognition opens up. I see a few options based off my own knowledge/Google -
use the methods isPlaying(MediaPlayer)/isSpeaking(TextToSpeech) and putting them in some kind of loop to check until they aren't true anymore, then opening the speech recognition.
Call Thread.sleep(). The problem I see with this is I'm not sure exactly how long user is going to speak so it could still get interrupted unless I put it at a high time which just slows the app down.
I've research and played around with the Handler class a bit, but haven't fully comprehended how to do this...anyone help?
If you want to do something when a MediaPlayer finishes, you can set a OnCompletionListener with setOnCompletionListener() to receive a callback when the media playback is complete.

Get the length of video recorded so far (or get accurate start time)

I want to synchronize other sensor data with the video I'm recording, and so I'd like to record "how far am I into the video" when the sensor is triggered. Is there any way to do this? I couldn't find an appropriate method on the MediaRecorder class.
Another solution would be to just get the precise start time of the video recording, but my tests show that the video starts ~1sec after calling mediarecorder.start, but it's not consistent.
You have raised an interesting topic.
If you refer to the documentation in the developer page, the following diagram states the recording is supposed to start when the start() method is called.
Your solution is supposed to be correct albeit there is a lag up to 1 sec. I would do it the same way
I went through the MediaRecorder class methods, the only method that seems to be useful is the callback setOnInfoListener().
Set it and see if you will get some kind of information when the recording starts! I haven't tried it yet though.

Android Programming: Looping Voice Recognition

I'm looking to make a custom Android app to help out a physically disabled person. I need to heavily rely on voice recognition. The idea would be:
the app (via voice recognition) accepts his speech
the app parses his speech and executes his commands ("email dad", "text fred", "what time is it?", etc, plus other things I'll be adding to control his tv, lights, etc)
after execution, the app waits for his next command (loop back to #1)
I have #1 & #2 working fine, but I can't figure out a good method for #3. I can't leave Google's voice recognition view running indefinitely because it could be hours before the next command. But the 'trigger' does have to be based on sound/voice. Has to be completely hands free.
Ideally, the app would just listen for a sound, and if that sound is above a certain pre-programmed decibel level, I'd start voice recognition. Is it possible to constantly loop just listening for a noise, then react if it's 'so' loud?
Any ideas?
Thanks
So the idea is that you want voice recognition to be ongoing. It is very hard to do that. But the way that I accomplished this is by using:
try {
Thread.sleep(4500);
mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
} catch (InterruptedException e) {
// It depends on your app logic what to do with InterruptedException
// You can process it or rethrow or restore interrupted flag
}
After the onReady (so if the user doesn't say something around 4.5 seconds it resets and at results. This worked great for me.
CMUSphinx is a great solution for this:
You can easily listen continuously, a voice detection API is provided
You can increase accuracy for a custom set of commands
You can adapt the model to the user voice thus increasing accuracy significantly
For more details on using CMUSphinx on Android see
http://cmusphinx.sourceforge.net/2011/05/building-pocketsphinx-on-android/

Java: How to implement listener to provide realtime audio stream position?

I'm working on an application to synchronize with realtime audio playback. I would like to define a listener with a specific timestep, and use the listener to get updates every time the audio being played has advanced by a timestep. Implementing this functionality must be possible (existence proof being time counter of audio player apps) but the architecture I have in mind might not be possible.
Ideally, I would listen to the audio stream on the SPEAKER or HEADPHONE Target Port of the sound card. The existing LineListener/LineEvent functionality only supports START/STOP/OPEN/CLOSE events, and I can't subclass and augment the Target Port implementation (or SourceDataLine or TargetDataLine).
How can I do this? Do I need to have a Thread constantly polling the getMicrosecondPosition() or getLongFramePosition() methods and fire my own event at the appropriate time? That sounds very inefficient. If I used a Timer to trigger the poll at regular time periods, then I'm better off than just using the system timers between the available START and STOP events that are supported on Port/DataLines. I would call the getMicrosecondPosition() method to synchronize, but I think that is likely to result in occaisional errors due to drift between the system Timer and real time audio. I'd expect to see repeats or skips of the counter (i.e. 1:23:003, 1:23:004, 1:23:006, 1:23:007... or 1:23:003, 1:23:004, 1:23:004, 1:23:005..).
I'm looking at the javazoom mp3 player source to see how they did it but no luck figuring it out so far. Any help/tips will be appreciated.

Categories