simple audio mixer, 2nd pass


The spec for setting the system property says this simply makes the option a “first choice”. If the option does not exist, then the normal default is used. So, I don’t think I did anything to introduce new problems by adding this to the code.

Now, I assume you (Julien) are able to get uncrackling sound normally. At the risk of trying your patience, would you be willing to check the ‘options’ menu I added to the Theremin? You might have done this once before.

This menu will list all the available output “mixers” on your system. I recall you had experienced crackle on my audio programs before. To diagnose, it would be helpful to me to have you report back what mixer options are presented by the dropdown. Also, if you could try each and tell me if any of them eliminate the crackle.

If one of the mixer options does eliminate the crackle, I can possibly give it a higher priority–make it the default for those systems that have it.

The theremin site is here:
The option button is in the top left.

Thank you!

Working perfectly here on Realtek HD Audio. Cool app, m8

JTheremin works fine whatever the mixer I choose and there is only one mixer available anyway.

Phil - is your code for the theremin mixer choice menu up somewhere? I’m not sure it’s offering all the options on my machine. Julien should probably be seeing at least 2 options.

What about a version of the code above that allows people to select buffersize, mixer and samplerate? I’m particularly wondering about samplerate, as there are a variety of issues around resampling that can cause crackling. PulseAudio or ALSA can be potentially running at a different samplerate to that you request from the output line, if it happens to be already running, or if the soundcard doesn’t properly support 44100Hz. I’ve noticed this cause crackling with lower latencies, and also heard of problems with audio clipping because of the resampling. The important option is probably 48kHz.

If I understand the code I wrote correctly ::), the line is rejected if it either does not match the format or is unavailable. Could that be the cause for the “missing” options?

Code for selecting a Mixer on the JTheremin:

	private void createMenuBars(){
		JMenuBar menuBar = new JMenuBar();
		menuBar.setBounds(0, 0, 60, 20);

		JMenu optionMenu = new JMenu("Options");
		JMenuItem pickMixers = new JMenuItem("Select a Playback Path");

		ButtonGroup mixerSelections = new ButtonGroup();

		addMixerOption("default sound system", mixerSelections, 
				optionMenu, true);

		AudioFormat audioFmt = new AudioFormat(
				44100, 16, 2, 4, 44100, false);
		Mixer.Info[] mixers = AudioSystem.getMixerInfo();
		for (Mixer.Info info : mixers) 
			Mixer mixer = AudioSystem.getMixer(info);

//				System.out.println(info);
				Info sdlLineInfo = new DataLine.Info(SourceDataLine.class, 
				SourceDataLine sdl = (SourceDataLine) mixer.getLine(sdlLineInfo);
				// if successful, add to list
				addMixerOption(info.getName() + " <> " + info.getDescription(),
						mixerSelections, optionMenu, false);
			catch (LineUnavailableException e) 
//				System.out.println("Mixer rejected, Line Unavailable: " + info);
			catch (IllegalArgumentException e)
//				System.out.println("Mixer rejected, Illegal Argument: " + info);

		add    (menuBar,0);	
	private void addMixerOption(String optionName, ButtonGroup bg,
			JMenu menu, boolean isSelected)
		JRadioButtonMenuItem newOption = new JRadioButtonMenuItem(optionName);
		newOption.addActionListener(new OptionListener());

I am quite taken by surprise if there are cards that don’t support 44100 or try to use 48kHz in place of 44100. I was putting off implementing the suggestions for additional options due to not running into concrete examples of problems caused. This is a concrete example, though!

I’d be really tempted to limit input to the mixer to 44100 Hz and say to folks use Audacity to convert your sound resources. That is simple enough to do, or to explain how to do. But I am at a bit of a loss as to how to play back 44100 Hz data on a 48k line. There could well be pre-built converters in Java but it is annoying to have to add another level of processing. (Reality is a bitch, yeah.)

By the way, as I said “for grins,” I tried running a version of the audio mixer that omits the last step of sending the filled buffer to the SourceDataLine, and it takes about 6 milliseconds of processing per audio second.

I still have to write the “buffered input” version, and to create tests with more audio tracks. However, this preliminary test suggests that the loss of performance by working on a per-sample basis from the inputs may not be of killing significance. For example if the buffer inputs were twice as performant, that saves only 3 milliseconds. Either way, the cpu would still have 99% of its capacity free for other tasks. (I don’t know what the % free would drop to yet, when adding more tracks.)

Well, I tried your code offline and it shows all the mixers fine. A bit of Googling suggests that the IcedTea policy files have a bug which doesn’t allow opening the PulseAudio mixer (because of its native lib). That means the default mixers in an applet and offline are different - joy! ::slight_smile:

I was going to say your code is probably longer than it needs to be and you could use mixer.isLineSupported(), however I’ve just noticed that the JavaDoc has some ambiguous documentation about some lines not being supported until the mixer is open. Hmm … never had a problem with that so far, but maybe trying to get the line is a safer bet after all, though it gives me the same output as your current code.

I get an error message about that even offline in JOAL:
AL lib: pulseaudio.c:612: Context did not connect: Access denied

If you’re using JOAL that’s a completely unrelated bug. This is a bug in the OpenJDK security manager settings for applets that doesn’t let it load the native libs in the JDK needed for PulseAudio.