I don't know very much about Java's MIDI function. In fact, it utterly bewilders me. what I'd like to do however is just build a simple application that will play one note.
How to play a single MIDI note using Java Sound?
The support for this out on the web is almost nonexistent, and I am totally at a loss.
I know this is a really old question, but, as a novice programmer, I had a very difficult time figuring out how to do this, so I thought I would share the following hello-world-style program that gets Java to play a single midi note in order to help anyone else getting started.
import javax.sound.midi.*;
public class MidiTest{
public static void main(String[] args) {
try{
/* Create a new Sythesizer and open it. Most of
* the methods you will want to use to expand on this
* example can be found in the Java documentation here:
* https://docs.oracle.com/javase/7/docs/api/javax/sound/midi/Synthesizer.html
*/
Synthesizer midiSynth = MidiSystem.getSynthesizer();
midiSynth.open();
//get and load default instrument and channel lists
Instrument[] instr = midiSynth.getDefaultSoundbank().getInstruments();
MidiChannel[] mChannels = midiSynth.getChannels();
midiSynth.loadInstrument(instr[0]);//load an instrument
mChannels[0].noteOn(60, 100);//On channel 0, play note number 60 with velocity 100
try { Thread.sleep(1000); // wait time in milliseconds to control duration
} catch( InterruptedException e ) {
e.printStackTrace();
}
mChannels[0].noteOff(60);//turn of the note
} catch (MidiUnavailableException e) {
e.printStackTrace();
}
}
}
The above code was primarily created by cutting, pasting, and messing around with code found in several online tutorials. Here are the most helpful tutorials that I found:
http://www.ibm.com/developerworks/library/it/it-0801art38/
This is a great tutorial and probably has everything you are looking for; however, it may be a little overwhelming at first.
http://patater.com/gbaguy/javamidi.htm
Features nonworking code written by a 15 year old. This was - surprisingly - the most helpful thing I found.
Here you go :
MIDI Tag Info on stackoverflow
UnderStanding MIDI
Tutorial on Oracle
Accessing MIDI
MIdi Synthesis
Related
Currently trying to access a type library file from JAVA, I have tried the following with corresponding errors:
1- Com2Java: I receive this Error Each time I try to connect to my application:
Minidumps are not enabled by default on client versions of Windows
2- Com4j: It produces only interfaces and Couldn't understand how to use them (I can't find any classes, just interfaces)
3- After a small search, found out about Visual J++ but couldnt download it coz it was discontnued.
Could anyone give advice?
Thank you
I have not used Com2Java or Com4j before, but a long time ago I used a library called JavaCOMBridge (https://sourceforge.net/projects/jacob-project/).
The version of JavaCOMBridge I used cannot handle multiple inheritance, and I don't see how there can be a good way to do it.
Forget about Visual J++. It's an abomination created by Microsoft and was sued into oblivion.
If you are experienced in both C and Java, and the amount of APIs you have to bridge is not large, I'd recommend using JNI directly.
Edit
Here's an example using Excel:
package test;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class JaCoBTest {
public static void main(String[] args) {
String EXCEL_FILE = "FullPathOfAnExcelFile.xlsx";
// Using Excel as an example
ActiveXComponent app = new ActiveXComponent("Excel.Application");
// Modify a property, to show Excel window
app.setProperty("Visible", true);
// Get Excel workbook object
Dispatch workbook = app.getProperty("Workbooks").toDispatch();
// Call method, to open an Excel file
Dispatch.call(workbook, "Open", new Variant(EXCEL_FILE), new Variant("1"));
// Wait for 5 seconds
try {
Thread.sleep(1000);
} catch (InterruptedException iex) {
iex.printStackTrace();
}
// Close Excel without saving
workbook.call(workbook, "Close");
// Close is supposed to have three optional parameteters, but the line below is not working
//workbook.call(workbook, "Close", new Variant(false), Variant.DEFAULT, Variant.DEFAULT);
// Close Excel
Dispatch.call(app, "Quit");
}
}
There is one problem in the above code - I cannot get optional parameters to work. The function Workbook.Close is supposed to take three optional parameters, but the call always fail with invalid number of parameters.
I've also located the web page I used back then:
http://danadler.com/jacob/
The above page contains a link to a FAQ but it's slightly outdated.
I am a beginner in programming. I am still learning about threads and more of them. But now I have quite a big idea to write my first program (I mean bigger than simple calculator). I want it to sort files, integrate in one (many copies of one file in different localization - the idea of it is of no importance now).
But I want to create threads, or anything else (what is your advice). I mean. When I start the program, the console starts up, and e.g I have to write "my_programm run" or "my_program stop" or "my_program status" or "my_magic_tricks be_done". I mean how can i create a program working in the background like in threads with real time string control over it.
I tried to find out on Google for anything which could be useful for me, but i didn't find it out.
Please give me just a name of libraries or methods, which I can use. I will read out, what it is about and finally I will move forward with it.
If it is a dumbass question. I am really sorry for disapointing the programmer group. But it would be nice to be given of any signpost or clue.
A simple way to do it using the standard library :
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class Example {
private static final int POOL_SIZE = 5;
private static final ExecutorService WORKERS = new ThreadPoolExecutor(POOL_SIZE, POOL_SIZE, 1, MILLISECONDS, new LinkedBlockingDeque<>());
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("> ");
String cmd = sc.nextLine();
switch (cmd) {
case "process":
WORKERS.submit(newExpensiveTask());
break;
case "kill":
System.exit(0);
default:
System.err.println("Unrecognized command: " + cmd);
}
}
}
private static Runnable newExpensiveTask() {
return () -> {
try {
Thread.sleep(10000);
System.out.println("Done processing");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
};
}
}
This code lets you run heavy tasks asynchronously while the user terminal remains available and reactive.
I would recommend reading up on specific tutorials, such as the Java Language Tutorial (available as a book - at least, it used to be - as well as on the Java website https://docs.oracle.com/javase/tutorial/essential/concurrency/)
However as others have cautioned, getting into threading is a challenge and requires good knowledge of the language quite apart from the aspects of multithreading and synchronization. I'd be tempted to recommend you read some of the other tutorials - working through IO and so on - first of all.
I am trying to play a wav/mp3 to my virtual audio cable, I have been searching for hours but can't seem to find how to achieve this. I have been able to play sound in both formats but I can't get it to output to 'Line-1' rather than 'Speakers'
Any helpful links or example code would be greatly appreciated.
To get an array of all Mixers on the current platform, you may use AudioSystem#getMixerInfo:
static void printAllMixerNames() {
for(Mixer.Info info : AudioSystem.getMixerInfo()) {
System.out.println(info.getName());
}
}
If your virtual cable is available, it will be in the array. For example, on my Mac the following is printed:
Java Sound Audio Engine
Built-in Input
Soundflower (2ch)
Soundflower (64ch)
Pro Tools Aggregate I/O
(Soundflower is a virtual device.)
To get some specific Mixer you unfortunately need to do String evaluation. So you need to discover its name, vendor, whatever, beforehand or give the user an option to pick one from a list.
static Mixer getMixerByName(String toFind) {
for(Mixer.Info info : AudioSystem.getMixerInfo()) {
if(toFind.equals(info.getName())) {
return AudioSystem.getMixer(info);
}
}
return null;
}
Once you have a particular Mixer you can obtain a Line or AudioInputStream from it. You can obtain a Clip from it through AudioSystem#getClip(Mixer.Info).
I am trying to play a wav/mp3...
javax.sound.sampled does not support mp3. Alternatives can be found here.
I have MP3 audio files that contain voicemails that are left by a computer.
The message content is always in same format and left by the same computer voice with only a slight variation in content:
"You sold 4 cars today" (where the 4 can be anything from 0 to 9).
I have be trying to set up Sphinx, but the out-of-the-box models did not work too good.
I then tried to write my own acoustic model and haven't had much better success yet (30% unrecognized is my best).
I am wondering if voice recognition might be overkill for this task since I have exactly ONE voice, an expected audio pattern and a very limited dictionary that would need to be recognized.
I have access to each of the ten sounds (spoken numbers) that I would need to search for in the message.
Is there a non-VR approach to finding sounds in an audio file (I can convert MP3 to another format if necessary).
Update: My solution to this task follows
After working with Nikolay directly, I learned that the answer to my original question is irrelevant since the desired results may be achieved (with 100% accuracy) using Sphinx4 and a JSGF grammar.
1: Since the speech in my audo files is very limited, I created a JSGF grammar (salesreport.gram) to describe it. All of the information I needed to create the following grammar was available on this JSpeech Grammar Format page.
#JSGF V1.0;
grammar salesreport;
public <salesreport> = (<intro> | <sales> | <closing>)+;
<intro> = this is your automated automobile sales report;
<sales> = you sold <digit> cars today;
<closing> = thank you for using this system;
<digit> = zero | one | two | three | four | five | six | seven | eight | nine;
NOTE: Sphinx does not support JSGF tags in the grammar. If necessary, a regular expression may be used to extract specific information (the number of sales in my case).
2: It is very important that your audio files are properly formatted. The default sample rate for Sphinx is 16Khz (16Khz means there are 16000 samples collected every second). I converted my MP3 audio files to WAV format using FFmpeg.
ffmpeg -i input.mp3 -acodec pcm_s16le -ac 1 -ar 16000 output.wav
Unfortunately, FFmpeg renders this solution OS dependent. I am still looking for a way to convert the files using Java and will update this post if/when I find it.
Although it was not required to complete this task, I found Audacity helpful for working with audio files. It includes many utilities for working with the audio files (checking sample rate and bandwidth, file format conversion, etc).
3: Since telephone audio has a maximum bandwidth (the range of frequencies included in the audio) of 8kHz, I used the Sphinx en-us-8khz acoustic model.
4: I generated my dictionary, salesreport.dic, using lmtool
5: Using the files mentioned in the previous steps and the following code (modified version of Nikolay's example), my speech is recognized with 100% accuracy every time.
public String parseAudio(File voiceFile) throws FileNotFoundException, IOException
{
String retVal = null;
StringBuilder resultSB = new StringBuilder();
Configuration configuration = new Configuration();
configuration.setAcousticModelPath("file:acoustic_models/en-us-8khz");
configuration.setDictionaryPath("file:salesreport.dic");
configuration.setGrammarPath("file:salesreportResources/")
configuration.setGrammarName("salesreport");
configuration.setUseGrammar(true);
StreamSpeechRecognizer recognizer = new StreamSpeechRecognizer(configuration);
try (InputStream stream = new FileInputStream(voiceFile))
{
recognizer.startRecognition(stream);
SpeechResult result;
while ((result = recognizer.getResult()) != null)
{
System.out.format("Hypothesis: %s\n", result.getHypothesis());
resultSB.append(result.getHypothesis()
+ " ");
}
recognizer.stopRecognition();
}
return resultSB.toString().trim();
}
The accuracy on such task must be 100%. Here is the code sample to use with the grammar:
public class TranscriberDemoGrammar {
public static void main(String[] args) throws Exception {
System.out.println("Loading models...");
Configuration configuration = new Configuration();
configuration.setAcousticModelPath("file:en-us-8khz");
configuration.setDictionaryPath("cmu07a.dic");
configuration.setGrammarPath("file:./");
configuration.setGrammarName("digits");
configuration.setUseGrammar(true);
StreamSpeechRecognizer recognizer =
new StreamSpeechRecognizer(configuration);
InputStream stream = new FileInputStream(new File("file.wav"));
recognizer.startRecognition(stream);
SpeechResult result;
while ((result = recognizer.getResult()) != null) {
System.out.format("Hypothesis: %s\n",
result.getHypothesis());
}
recognizer.stopRecognition();
}
}
You also need to make sure that both sample rate and audio bandwidth matches the decoder configuration
http://cmusphinx.sourceforge.net/wiki/faq#qwhat_is_sample_rate_and_how_does_it_affect_accuracy
First of all, Sphinx only work with WAVE file. For very limited vocabulary, Sphinx should generate good result when using a JSGF grammar file (but not that good in dictation mode). The main issue I found is that it does not provide confidence score (it is currently bugged). You might want to check three other alternative:
SpeechRecognizer from Windows platform. It provide easy to use recognition with confidence score and support grammar. This is C#, but you could build a native wrapper or custom server.
Google Speech API is an online speech recognition engine, free up to 50 request per day. There is several API for this, but I like JARVIS. Be careful though, since there is no official support or documentation about this and Google might (and already have in the past) close this engine whenever they want. Of course, you will have some privacy issue (is it okay to send this audio data to a third party ?).
I recently came through ISpeech and got good result with it. It provides its own Java wrapper API, free for mobile app. Same privacy issue as Google API.
I myself choose to go with the first option and build a speech recognition service in a custom http server. I found it to be the most effective way to tackle speech recognition from Java until Sphinx scoring issue is fixed.
I would like to get to query Windows Vista Search service directly ( or indirectly ) from Java.
I know it is possible to query using the search-ms: protocol, but I would like to consume the result within the app.
I have found good information in the Windows Search API but none related to Java.
I would mark as accepted the answer that provides useful and definitive information on how to achieve this.
Thanks in advance.
EDIT
Does anyone have a JACOB sample, before I can mark this as accepted?
:)
You may want to look at one of the Java-COM integration technologies. I have personally worked with JACOB (JAva COm Bridge):
http://danadler.com/jacob/
Which was rather cumbersome (think working exclusively with reflection), but got the job done for me (quick proof of concept, accessing MapPoint from within Java).
The only other such technology I'm aware of is Jawin, but I don't have any personal experience with it:
http://jawinproject.sourceforge.net/
Update 04/26/2009:
Just for the heck of it, I did more research into Microsoft Windows Search, and found an easy way to integrate with it using OLE DB. Here's some code I wrote as a proof of concept:
public static void main(String[] args) {
DispatchPtr connection = null;
DispatchPtr results = null;
try {
Ole32.CoInitialize();
connection = new DispatchPtr("ADODB.Connection");
connection.invoke("Open",
"Provider=Search.CollatorDSO;" +
"Extended Properties='Application=Windows';");
results = (DispatchPtr)connection.invoke("Execute",
"select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
"from SystemIndex " +
"where contains('Foo')");
int count = 0;
while(!((Boolean)results.get("EOF")).booleanValue()) {
++ count;
DispatchPtr fields = (DispatchPtr)results.get("Fields");
int numFields = ((Integer)fields.get("Count")).intValue();
for (int i = 0; i < numFields; ++ i) {
DispatchPtr item =
(DispatchPtr)fields.get("Item", new Integer(i));
System.out.println(
item.get("Name") + ": " + item.get("Value"));
}
System.out.println();
results.invoke("MoveNext");
}
System.out.println("\nCount:" + count);
} catch (COMException e) {
e.printStackTrace();
} finally {
try {
results.invoke("Close");
} catch (COMException e) {
e.printStackTrace();
}
try {
connection.invoke("Close");
} catch (COMException e) {
e.printStackTrace();
}
try {
Ole32.CoUninitialize();
} catch (COMException e) {
e.printStackTrace();
}
}
}
To compile this, you'll need to make sure that the JAWIN JAR is in your classpath, and that jawin.dll is in your path (or java.library.path system property). This code simply opens an ADO connection to the local Windows Desktop Search index, queries for documents with the keyword "Foo," and print out a few key properties on the resultant documents.
Let me know if you have any questions, or need me to clarify anything.
Update 04/27/2009:
I tried implementing the same thing in JACOB as well, and will be doing some benchmarks to compare performance differences between the two. I may be doing something wrong in JACOB, but it seems to consistently be using 10x more memory. I'll be working on a jcom and com4j implementation as well, if I have some time, and try to figure out some quirks that I believe are due to the lack of thread safety somewhere. I may even try a JNI based solution. I expect to be done with everything in 6-8 weeks.
Update 04/28/2009:
This is just an update for those who've been following and curious. Turns out there are no threading issues, I just needed to explicitly close my database resources, since the OLE DB connections are presumably pooled at the OS level (I probably should have closed the connections anyway...). I don't think I'll be any further updates to this. Let me know if anyone runs into any problems with this.
Update 05/01/2009:
Added JACOB example per Oscar's request. This goes through the exact same sequence of calls from a COM perspective, just using JACOB. While it's true JACOB has been much more actively worked on in recent times, I also notice that it's quite a memory hog (uses 10x as much memory as the Jawin version)
public static void main(String[] args) {
Dispatch connection = null;
Dispatch results = null;
try {
connection = new Dispatch("ADODB.Connection");
Dispatch.call(connection, "Open",
"Provider=Search.CollatorDSO;Extended Properties='Application=Windows';");
results = Dispatch.call(connection, "Execute",
"select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
"from SystemIndex " +
"where contains('Foo')").toDispatch();
int count = 0;
while(!Dispatch.get(results, "EOF").getBoolean()) {
++ count;
Dispatch fields = Dispatch.get(results, "Fields").toDispatch();
int numFields = Dispatch.get(fields, "Count").getInt();
for (int i = 0; i < numFields; ++ i) {
Dispatch item =
Dispatch.call(fields, "Item", new Integer(i)).
toDispatch();
System.out.println(
Dispatch.get(item, "Name") + ": " +
Dispatch.get(item, "Value"));
}
System.out.println();
Dispatch.call(results, "MoveNext");
}
} finally {
try {
Dispatch.call(results, "Close");
} catch (JacobException e) {
e.printStackTrace();
}
try {
Dispatch.call(connection, "Close");
} catch (JacobException e) {
e.printStackTrace();
}
}
}
As few posts here suggest you can bridge between Java and .NET or COM using commercial or free frameworks like JACOB, JNBridge, J-Integra etc..
Actually I had an experience with with one of these third parties (an expensive one :-) ) and I must say I will do my best to avoid repeating this mistake in the future. The reason is that it involves many "voodoo" stuff you can't really debug, it's very complicated to understand what is the problem when things go wrong.
The solution I would suggest you to implement is to create a simple .NET application that makes the actual calls to the windows search API. After doing so, you need to establish a communication channel between this component and your Java code. This can be done in various ways, for example by messaging to a small DB that your application will periodically pull. Or registering this component on the machine IIS (if exists) and expose simple WS API to communicate with it.
I know that it may sound cumbersome but the clear advantages are: a) you communicate with windows search API using the language it understands (.NET or COM) , b) you control all the application paths.
Any reason why you couldn't just use Runtime.exec() to query via search-ms and read the BufferedReader with the result of the command? For example:
public class ExecTest {
public static void main(String[] args) throws IOException {
Process result = Runtime.getRuntime().exec("search-ms:query=microsoft&");
BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
StringBuffer outputSB = new StringBuffer(40000);
String s = null;
while ((s = output.readLine()) != null) {
outputSB.append(s + "\n");
System.out.println(s);
}
String result = output.toString();
}
}
There are several libraries out there for calling COM objects from java, some are opensource (but their learning curve is higher) some are closed source and have a quicker learning curve. A closed source example is EZCom. The commercial ones tend to focus on calling java from windows as well, something I've never seen in opensource.
In your case, what I would suggest you do is front the call in your own .NET class (I guess use C# as that is closest to Java without getting into the controversial J#), and focus on making the interoperability with the .NET dll. That way the windows programming gets easier, and the interface between Windows and java is simpler.
If you are looking for how to use a java com library, the MSDN is the wrong place. But the MSDN will help you write what you need from within .NET, and then look at the com library tutorials about invoking the one or two methods you need from your .NET objects.
EDIT:
Given the discussion in the answers about using a Web Service, you could (and probably will have better luck) build a small .NET app that calls an embedded java web server rather than try to make .NET have the embedded web service, and have java be the consumer of the call. For an embedded web server, my research showed Winstone to be good. Not the smallest, but is much more flexible.
The way to get that to work is to launch the .NET app from java, and have the .NET app call the web service on a timer or a loop to see if there is a request, and if there is, process it and send the response.