5

I've been reading up on the Java Sound API for the last few weeks and I still can't figure out if this is possible. I ask because I want to write a program that takes sound data passing through the system headed for an output line, like my computer's speakers or headphone jack, and writes that data to an audio file.

From what I have read so far about javax.sound.sampled, it seems like I can only read in data from a Mixer via a TargetDataLine; however, after writing a test program (provided below) to query my system for available mixers and then query those mixers for available target and source data lines; I realized all my output mixers except for my default mixer only supported SourceDataLines. Furthermore, I can't tell whether the TargetDataLine from my computer's default mixer (I have a Macbook pro), can read audio data sent to the mixer from other applications. So before I delve further into this project, I want to figure out if it's even possible to access sound being sent through mixers by other applications.

Test Program

import javax.sound.sampled.*;
import java.util.Scanner;

public class Capture {
    public static final String ANSI_RED = "\u001B[31m";
    public static final String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_RESET = "\u001B[m";

    private Mixer mixer;

    public Capture() {
        Mixer.Info[] installedMixers = AudioSystem.getMixerInfo();
        for(int n = 0; n < installedMixers.length; n++) {
            System.out.println(ANSI_GREEN + "[" + n + "] " + ANSI_RESET + installedMixers[n].toString());
        }
        while(mixer == null) {
            int choice;
            try {
                System.out.print("Choose a mixer: ");
                Scanner s = new Scanner(System.in);
                choice = s.nextInt();
                if(choice >= 0 && choice < installedMixers.length)
                    mixer = AudioSystem.getMixer(installedMixers[choice]);
                else
                    System.out.println(ANSI_RED + "Invalid Choice!" + ANSI_RESET);
            } catch(RuntimeException e) {
                System.out.println(ANSI_RED + "Please input an integer corresponding to your mixer choice." + ANSI_RESET);
            }
        }
        System.out.println(ANSI_RED + "Source Lines:" + ANSI_RESET);
        Line.Info[] sourceLines = mixer.getSourceLineInfo();
        if(sourceLines.length == 0) {
            System.out.println("None");
        }
        for(int n = 0; n < sourceLines.length; n++) {
            System.out.println(ANSI_GREEN + "[" + n + "] " + ANSI_RESET + sourceLines[n].toString());
        }
        System.out.println(ANSI_RED + "Target Lines:" + ANSI_RESET);
        Line.Info[] targetLines = mixer.getTargetLineInfo();
        if(targetLines.length == 0) {
            System.out.println("None");
        }
        for(int n = 0; n < targetLines.length; n++) {
            System.out.println(ANSI_GREEN + "[" + n + "] " + ANSI_RESET + targetLines[n].toString());
        }

    }

    public static void main(String[] args) {
        Capture recording = new Capture();
    }
}

P.S. I found a 2 other questions related to this exact topic that didn't seem to provide solutions at all. One was never answered, the other had a solution that didn't work for the asker, and that I couldn't reproduce.

Community
  • 1
  • 1
Will Byrne
  • 681
  • 7
  • 15
  • To view the `DataLine` objects of a PC, see also `MediaTypes` in [this answer](http://stackoverflow.com/a/7616206/418556). I wrote an app. that tapped into the system sound lines to display a trace of the signal on-screen. It worked perfectly on some Windows based machines, failed completely (no suitable line) on others. I was led to understand that the Apple Java Sound API support on OS X was even shakier, though that was from before the Oracle JRE for the Mac. – Andrew Thompson Aug 12 '14 at 12:23
  • @AndrewThompson Thanks for responding! Your `MediaTypes` app acts as a much better test app than the one I wrote. Would you be willing to share the source code for the app you wrote to tap into the system sound lines and display a trace of the signal? It would even be helpful to me if you just shared your method for tapping the sound lines. Also, if it turns out that this flat out isn't possible using the Java Sound API alone, is there some way I could implement a solution in another language using a `native` method? Again, thanks so much for taking the time to help. – Will Byrne Aug 12 '14 at 13:54

0 Answers0