0 Replies Latest reply: Dec 3, 2011 12:23 PM by 293484 RSS

    Merging and saving audio capture + file from disk

    293484
      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