Working with audio in Java

2019-05-23 12:31发布

问题:

I went over Java's tutorial on sounds but somehow it is way too complex for a beginner.
It is here
My aim is this:

  • Detect all the audio input and output devices
  • let the user select a audio input device
  • capture what the user says
  • output it to the default audio output device
  • Now how do I go about doing that?
    Is there a better tutorial available?
    What I have tried:

    import javax.sound.sampled.*;
    public class SoundTrial {
        public static void main(String[] args) {
            Mixer.Info[] info = AudioSystem.getMixerInfo();
            int i =0;
            for(Mixer.Info print : info){
    
                System.out.println("Name: "+ i + " " + print.getName());
                i++;
            }
        }
    }  
    

    output:

    Name: 0 Primary Sound Driver
    Name: 1 Speakers and Headphones (IDT High Definition Audio CODEC)
    Name: 2 Independent Headphones (IDT High Definition Audio CODEC
    Name: 3 SPDIF (Digital Out via HP Dock) (IDT High Definition Audio CODEC)
    Name: 4 Primary Sound Capture Driver
    Name: 5 Integrated Microphone Array (ID
    Name: 6 Microphone (IDT High Definition
    Name: 7 Stereo Mix (IDT High Definition
    Name: 8 Port Speakers and Headphones (IDT Hi
    Name: 9 Port SPDIF (Digital Out via HP Dock)
    Name: 10 Port Integrated Microphone Array (ID
    Name: 11 Port Microphone (IDT High Definition
    Name: 12 Port Stereo Mix (IDT High Definition
    Name: 13 Port Independent Headphones (IDT Hi
    

    回答1:

    This code may help you. Note this has been taken from this link: Audio Video. I found using Google search, I just posted code here in-case link becomes outdated.

    
    import javax.media.*;
    import javax.media.format.*;
    import javax.media.protocol.*;
    import java.util.*;
    
    /*******************************************************************************
     * A simple application to allow users to capture audio or video through devices
     * connected to the PC. Via command-line arguments the user specifies whether
     * audio (-a) or video (-v) capture, the duration of the capture (-d) in
     * seconds, and the file to write the media to (-f).
     * 
     * The application would be far more useful and versatile if it provided control
     * over the formats of the audio and video captured as well as the content type
     * of the output.
     * 
     * The class searches for capture devices that support the particular default
     * track formats: linear for audio and Cinepak for video. As a fall-back two
     * device names are hard-coded into the application as an example of how to
     * obtain DeviceInfo when a device's name is known. The user may force the
     * application to use these names by using the -k (known devices) flag.
     * 
     * The class is static but employs the earlier Location2Location example to
     * perform all the Processor and DataSink related work. Thus the application
     * chiefly involves CaptureDevice related operations.
     * 
     * @author Michael (Spike) Barlow
     ******************************************************************************/
    public class SimpleRecorder {
    
      /////////////////////////////////////////////////////////////
      // Names for the audio and video capture devices on the
      // author's system. These will vary system to system but are
      // only used as a fallback.
      /////////////////////////////////////////////////////////////
      private static final String AUDIO_DEVICE_NAME = "DirectSoundCapture";
    
      private static final String VIDEO_DEVICE_NAME = "vfw:Microsoft WDM Image Capture:0";
    
      ///////////////////////////////////////////////////////////
      // Default names for the files to write the output to for
      // the case where they are not supplie by the user.
      //////////////////////////////////////////////////////////
      private static final String DEFAULT_AUDIO_NAME = "file://./captured.wav";
    
      private static final String DEFAULT_VIDEO_NAME = "file://./captured.avi";
    
      ///////////////////////////////////////////
      // Type of capture requested by the user.
      //////////////////////////////////////////
      private static final String AUDIO = "audio";
    
      private static final String VIDEO = "video";
    
      private static final String BOTH = "audio and video";
    
      ////////////////////////////////////////////////////////////////////
      // The only audio and video formats that the particular application
      // supports. A better program would allow user selection of formats
      // but would grow past the small example size.
      ////////////////////////////////////////////////////////////////////
      private static final Format AUDIO_FORMAT = new AudioFormat(
          AudioFormat.LINEAR);
    
      private static final Format VIDEO_FORMAT = new VideoFormat(
          VideoFormat.CINEPAK);
    
      public static void main(String[] args) {
    
        //////////////////////////////////////////////////////
        // Object to handle the processing and sinking of the
        // data captured from the device.
        //////////////////////////////////////////////////////
        Location2Location capture;
    
        /////////////////////////////////////
        // Audio and video capture devices.
        ////////////////////////////////////
        CaptureDeviceInfo audioDevice = null;
        CaptureDeviceInfo videoDevice = null;
    
        /////////////////////////////////////////////////////////////
        // Capture device's "location" plus the name and location of
        // the destination.
        /////////////////////////////////////////////////////////////
        MediaLocator captureLocation = null;
        MediaLocator destinationLocation;
        String destinationName = null;
    
        ////////////////////////////////////////////////////////////
        // Formats the Processor (in Location2Location) must match.
        ////////////////////////////////////////////////////////////
        Format[] formats = new Format[1];
    
        ///////////////////////////////////////////////
        // Content type for an audio or video capture.
        //////////////////////////////////////////////
        ContentDescriptor audioContainer = new ContentDescriptor(
            FileTypeDescriptor.WAVE);
        ContentDescriptor videoContainer = new ContentDescriptor(
            FileTypeDescriptor.MSVIDEO);
        ContentDescriptor container = null;
    
        ////////////////////////////////////////////////////////////////////
        // Duration of recording (in seconds) and period to wait afterwards
        ///////////////////////////////////////////////////////////////////
        double duration = 10;
        int waitFor = 0;
    
        //////////////////////////
        // Audio or video capture?
        //////////////////////////
        String selected = AUDIO;
    
        ////////////////////////////////////////////////////////
        // All devices that support the format in question.
        // A means of "ensuring" the program works on different
        // machines with different capture devices.
        ////////////////////////////////////////////////////////
        Vector devices;
    
        //////////////////////////////////////////////////////////
        // Whether to search for capture devices that support the
        // format or use the devices whos names are already
        // known to the application.
        //////////////////////////////////////////////////////////
        boolean useKnownDevices = false;
    
        /////////////////////////////////////////////////////////
        // Process the command-line options as to audio or video,
        // duration, and file to save to.
        /////////////////////////////////////////////////////////
        for (int i = 0; i  0 && !useKnownDevices) {
            audioDevice = (CaptureDeviceInfo) devices.elementAt(0);
          } else
            audioDevice = CaptureDeviceManager.getDevice(AUDIO_DEVICE_NAME);
          if (audioDevice == null) {
            System.out.println("Can't find suitable audio device. Exiting");
            System.exit(1);
          }
          captureLocation = audioDevice.getLocator();
          formats[0] = AUDIO_FORMAT;
          if (destinationName == null)
            destinationName = DEFAULT_AUDIO_NAME;
          container = audioContainer;
        }
        /////////////////////////////////////////////////////////////////
        // Perform setup for video capture. Includes finding a suitable
        // device, obatining its MediaLocator and setting the content
        // type.
        ////////////////////////////////////////////////////////////////
        else if (selected.equals(VIDEO)) {
          devices = CaptureDeviceManager.getDeviceList(VIDEO_FORMAT);
          if (devices.size() > 0 && !useKnownDevices)
            videoDevice = (CaptureDeviceInfo) devices.elementAt(0);
          else
            videoDevice = CaptureDeviceManager.getDevice(VIDEO_DEVICE_NAME);
          if (videoDevice == null) {
            System.out.println("Can't find suitable video device. Exiting");
            System.exit(1);
          }
          captureLocation = videoDevice.getLocator();
          formats[0] = VIDEO_FORMAT;
          if (destinationName == null)
            destinationName = DEFAULT_VIDEO_NAME;
          container = videoContainer;
        } else if (selected.equals(BOTH)) {
          captureLocation = null;
          formats = new Format[2];
          formats[0] = AUDIO_FORMAT;
          formats[1] = VIDEO_FORMAT;
          container = videoContainer;
          if (destinationName == null)
            destinationName = DEFAULT_VIDEO_NAME;
        }
    
        ////////////////////////////////////////////////////////////////////
        // Perform all the necessary Processor and DataSink preparation via
        // the Location2Location class.
        ////////////////////////////////////////////////////////////////////
        destinationLocation = new MediaLocator(destinationName);
        System.out.println("Configuring for capture. Please wait.");
        capture = new Location2Location(captureLocation, destinationLocation,
            formats, container, 1.0);
    
        /////////////////////////////////////////////////////////////////////////////
        // Start the recording and tell the user. Specify the length of the
        // recording. Then wait around for up to 4-times the duration of
        // recording
        // (can take longer to sink/write the data so should wait a bit incase).
        /////////////////////////////////////////////////////////////////////////////
        System.out.println("Started recording " + duration + " seconds of "
            + selected + " ...");
        capture.setStopTime(new Time(duration));
        if (waitFor == 0)
          waitFor = (int) (4000 * duration);
        else
          waitFor *= 1000;
        int waited = capture.transfer(waitFor);
    
        /////////////////////////////////////////////////////////
        // Report on the success (or otherwise) of the recording.
        /////////////////////////////////////////////////////////
        int state = capture.getState();
        if (state == Location2Location.FINISHED)
          System.out.println(selected
              + " capture successful in approximately "
              + ((int) ((waited + 500) / 1000))
              + " seconds. Data written to " + destinationName);
        else if (state == Location2Location.FAILED)
          System.out.println(selected
              + " capture failed after approximately "
              + ((int) ((waited + 500) / 1000)) + " seconds");
        else {
          System.out.println(selected
              + " capture still ongoing after approximately "
              + ((int) ((waited + 500) / 1000)) + " seconds");
          System.out.println("Process likely to have failed");
        }
    
        System.exit(0);
      }
    }