This discussion is archived
0 Replies Latest reply: Dec 3, 2011 10:23 AM by 293484 RSS

Merging and saving audio capture + file from disk

293484 Newbie
Currently Being Moderated
Hi,

I need to combine an audio file (read from disk) with an audio capture from a microphone and save the combined audio to a file.
I created processors for both, merged the data sources and created a processor from the merged data source.
If I use that as an input to a player, it seems to play OK : I hear the combination of the audio file and the microphone over the speakers (albeit with a delay of the microphone input).

But when I try to save this merged processor's data source (I tried 2 different ways based on samples I found) I get the following exceptions respectively
writeToFile
javax.media.NoDataSinkException: Cannot find a DataSink for: com.sun.media.multiplexer.RawBufferMux$RawBufferDataSource@121cc40
     at javax.media.Manager.createDataSink(Manager.java:1894)
     at soundTest.MergeTest4.writeToFile(MergeTest4.java:108)
     at soundTest.MergeTest4.runTest(MergeTest4.java:70)
     at soundTest.MergeTest4.main(MergeTest4.java:207)

writeToFile2:
Unable to handle format: LINEAR, 44100.0 Hz, 16-bit, Stereo, LittleEndian, Signed
Unable to handle format: LINEAR, 44100.0 Hz, 16-bit, Stereo, LittleEndian, Signed, 176400.0 frame rate, FrameSize=32 bits
Failed to realize: com.sun.media.ProcessEngine@691f36
Error: Unable to realize com.sun.media.ProcessEngine@691f36
javax.media.CannotRealizeException
     at javax.media.Manager.blockingCall(Manager.java:2005)
     at javax.media.Manager.createRealizedProcessor(Manager.java:914)
     at soundTest.MergeTest4.saveFile(MergeTest4.java:83)
     at soundTest.MergeTest4.runTest(MergeTest4.java:71)
     at soundTest.MergeTest4.main(MergeTest4.java:208

Here's the code (apologies for heavy use of static and poor error handling)
public class MergeTest4 {
       private static final Format AUDIO_FORMAT = new AudioFormat(AudioFormat.LINEAR);
       private static final int TIME_OUT = 2000;
       
     private static void runTest() throws Exception {
          
       DataSource ds1 = getCaptureDataSource();
       DataSource ds2 = Manager.createDataSource(new URL("file:///c:/temp/test.wav"));
       
       Processor processor1 = Manager.createProcessor(ds1);           
       Processor processor2 = Manager.createProcessor(ds2);   
       
       configureAndStart(processor1);
       configureAndStart(processor2);
         
       DataSource[] sources = { processor1.getDataOutput(), processor2.getDataOutput()};
       DataSource mergedDS = Manager.createMergingDataSource(sources);
          
       Processor mergedProcessor = Manager.createProcessor(mergedDS);     
       configureAndStart(mergedProcessor);
       
   
        //This works
        Player player = Manager.createRealizedPlayer(mergedProcessor.getDataOutput());
         player.start();          
                      
         //This does not work
         //  writeToFile(mergedProcessor);
         //  writeToFile2(mergedProcessor);
          
     }
     

    private static void writeToFile2(Processor processor) throws Exception {
         
          ProcessorModel outputPM = new ProcessorModel(processor.getDataOutput(),
                new Format[]{ new AudioFormat(AudioFormat.LINEAR)},
                new FileTypeDescriptor(FileTypeDescriptor.WAVE)
                );

        MediaLocator dest = new MediaLocator("file://./rec.wav");
        Processor outputProcessor = Manager.createRealizedProcessor(outputPM);
        DataSource newDS = outputProcessor.getDataOutput();
        newDS.connect();
        newDS.start();
      
        DataSink dataSink = Manager.createDataSink(newDS, dest);
        dataSink.open();
        dataSink.start();
      //  dataSink.addDataSinkListener(this);

        outputProcessor.start();

}
     private static void writeToFile(Processor processor) throws Exception {
                     
          StateHelper sh = new StateHelper(processor);
          
          if (!sh.realize(10000)) {
               System.exit(-1);
           }

           processor.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.WAVE));
           MediaLocator dest = new MediaLocator("file://c:/temp/foo.wav");
           DataSink filewriter = Manager.createDataSink(processor.getDataOutput(), dest);
           filewriter.open();
           StreamWriterControl swc = (StreamWriterControl) processor.getControl("javax.media.control.StreamWriterControl");
           
           //set limit to 5MB
           if (swc != null) {
               swc.setStreamSizeLimit(5000000);
           }

           try {
               filewriter.start();
           } catch (IOException e) {
               System.exit(-1);
           }
           
           // Capture for 20 seconds
           sh.playToEndOfMedia(20000);
           sh.close();

           filewriter.close();
     }


     private static DataSource getCaptureDataSource() {
          try {
               Vector captureDevices = CaptureDeviceManager.getDeviceList(AUDIO_FORMAT);
                
                CaptureDeviceInfo audiocaptureDevice=null;
                if (captureDevices.size() > 0) {
                     audiocaptureDevice = (CaptureDeviceInfo) captureDevices.get(0);
                } else {
                     System.out.println("Can't find suitable audio capture device.");
                    return null;
                }
                
                return Manager.createDataSource(audiocaptureDevice.getLocator());
          } catch (Exception ex) {
               ex.printStackTrace();
          }
          return null;
     }
     
     private static void start(Player player) {
          player.start();
          waitForState(player, Processor.Realized);
     }
     
     private static void configure(Processor p) {
          p.configure();
          waitForState(p, Processor.Configured);
     }
     
     private static void configureAndStart(Processor p) {
          p.configure();
          waitForState(p, Processor.Configured);
          start(p);
     }
     
     private static void waitForState(Player player, int state) {
        
         if (player.getState() == state) {
             return;
         }

         long startTime = new Date().getTime();
         final Object waitListener = new Object();

         ControllerListener cl = new ControllerListener() {

             @Override
             public void controllerUpdate(ControllerEvent ce) {
                 synchronized (waitListener) {
                     waitListener.notifyAll();
                 }
             }
         };
         
         try {
             player.addControllerListener(cl);

             synchronized (waitListener) {
                 while (player.getState() != state && new Date().getTime() - startTime < TIME_OUT) {
                     try {
                         waitListener.wait(500);
                     } catch (InterruptedException ex) {
                         ex.printStackTrace();
                     }
                 }
             }
         } finally {
             player.removeControllerListener(cl);
         }
     }
     
Any idea what needs to be changed for this to work?

Thanks

Philippe

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points