We help IT Professionals succeed at work.

how to read clip property in a directory

Mike Eghtebas
on
Please rename cartcar.pdf (attached) as cartcar.wav to test it with the attached code. This audio clip is about 3.5 seconds. When it plays it to the end, using following lines, it disable Stop button.

    private class TimerListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if (t<=0) stop();
        }
    }

The value t in millisecond is set at:

    public void start() {
        t =3650; //<----*********
        timer.start();
        audioClip.play();
        play.setEnabled(false);
        stop.setEnabled(true);
        loop.setEnabled(true);          
    }

Above, I have entered t =3650 manually. But it will be good if I could read this property and enter it using some code (see the attached image).

Question: How can I read the length of video in seconds from the property of the clip using code?

Thank you.  
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;

public class Exercise18_20 extends JApplet { 

    private JButton play = new JButton("Play");
    private JButton loop = new JButton("Loop");
    private JButton stop = new JButton("Stop");
    private AudioClip audioClip;
    private int t =0;
    private Timer timer = new Timer(0, new TimerListener());
    
    public Exercise18_20() {

        audioClip = Applet.newAudioClip(getClass().getResource("cartcar.wav"));
        JPanel pane = new JPanel(new FlowLayout());

        JPanel panel = new JPanel();
        panel.add(play);
        panel.add(loop);
        panel.add(stop);
        stop.setEnabled(false);
        add(panel, BorderLayout.CENTER);
        
        play.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    start();
                }
        });
        loop.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    loop();
                }
        });
        stop.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    stop();
                }
        });

        timer.start();
        
    }

    private class TimerListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
System.out.println(t--);
            if (t<=0) stop();
        }
    }    
  
    public void start() {
        t =3650;
        timer.start();
        audioClip.play();
        play.setEnabled(false);
        stop.setEnabled(true);
        loop.setEnabled(true);          
    }
    
    public void loop() {
        stop();
        audioClip.loop();
        loop.setEnabled(false);
        play.setEnabled(true); 
        stop.setEnabled(true);        
    }    
    
    public void stop() {
        timer.stop();
        audioClip.stop();
        stop.setEnabled(false);
        loop.setEnabled(true);
        play.setEnabled(true);       
    }    

    public static void main(String[] args) {

        Exercise18_20 player = new Exercise18_20();
        
         JFrame frame = new JFrame("Exercise18_20");
        Exercise18_20 applet = new Exercise18_20();
        applet.init();
        
        frame.getContentPane().add(applet, BorderLayout.CENTER);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.setSize(250,75);
        frame.setVisible(true);       
    }
}

Open in new window

cartcar.zip
property.png
Comment
Watch Question

Awarded 2011
Awarded 2011

Commented:

These are in general windows specific properties.
In this trail

http://www.cplusplus.com/forum/windows/24603/

there is a suggestion how to do it through JNI call to native
C++ fuction and the function itself

This would not be easy though

Thanks everyone.

Provided solution worked perfectly. I modified it a little bit like this:

	

const char * _filename = "E:\\test\\folder_µ_1\\Backup-0008.txt";
const TCHAR * file = _T(_filename);
WIN32_FILE_ATTRIBUTE_DATA fileAttrs;
BOOL result = GetFileAttributesEx(file, GetFileExInfoStandard, &fileAttrs);



I tested it in a simple C++ application and it worked perfectly. It worked for both ascii filepath and Unicode filepath. I also tried to get file size from fileAttrs structure and it was correct.

Now let me explain the situation in more details. I created a function using the code above in a C++ dll like this:


JNIEXPORT jlong JNICALL Java_FileAttrs_getAttrib(JNIEnv *env, jobject obj, jstring filename) 
{
   const char * _filename = env->GetStringUTFChars(filename, 0);
   const TCHAR * file = _T(_filename);
   printf("\n>>>_filename: "); printf(_filename);
   printf("\n>>>     file: "); printf(file);
   WIN32_FILE_ATTRIBUTE_DATA fileAttrs;
   BOOL result = GetFileAttributesEx(file, GetFileExInfoStandard, &fileAttrs);
   if (!result) {
      return -1;
   }
   return fileAttrs.dwFileAttributes;
}



This dll function is called from a Java application using jni (for Java, I’m using Eclipse). This java app sends filepath as a parameter to this dll function. Java has no problem with ascii and Unicode file paths. Now if the filepath has only ascii characters in it, C++ function works correctly and returns file attributes but if the filepath contains Unicode characters C++ function fails and return -1. I hard-coded the value of _filename variable for testing purpose and then called the function from Java using Eclipse and it worked perfectly.

1
2
	

//const char * _filename = env->GetStringUTFChars(filename, 0);
const char * _filename = "E:\\test\\folder_µ_1\\Backup-0008.txt";



So I suppose that env->GetStringUTFChars(filename, 0) function is creating problem.

The printf() statements in the code produced following output (captured from Eclipse output window):

When using env->GetStringUTFChars(filename, 0):
const char * _filename = env->GetStringUTFChars(filename, 0);
>>>_filename: E:\test\folder_µ_1\Backup-0008.txt
>>> file: E:\test\folder_µ_1\Backup-0008.txt

When using hard-coded value:
const char * _filename = "E:\\test\\folder_µ_1\\Backup-0008.txt";
>>>_filename: E:\test\folder_µ_1\Backup-0008.txt
>>> file: E:\test\folder_µ_1\Backup-0008.txt

You can see that printf() displayed correct filepath when hard-coded.

Maybe I need to convert utf chars to Unicode/ascii chars somehow.

Sorry if it is not related to the forum anymore.

Open in new window

Awarded 2011
Awarded 2011

Commented:
Awarded 2011
Awarded 2011

Commented:

the instance of this class:
http://docs.oracle.com/javase/6/docs/api/javax/sound/sampled/AudioFileFormat.html

can be obtained frfom file:

public static AudioFileFormat getAudioFileFormat(File file)

then getProperty("duration") should give the length in microseconds

Now Ill try but I don't have much hope frabnkly
Awarded 2011
Awarded 2011

Commented:


AudioFileFormat aff = AudioSystem.getAudioFileFormat(File file)
System.out.println(aff.getProperty("duration"));

Open in new window

Awarded 2011
Awarded 2011
Commented:
Look, I got windows parameters in in toString() method of AudioFileFormat:

  
                             try{
                  AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("tada.wav"));
                                 Map<String, Object> m = aff.properties();
                                 System.out.println("m: " + m);

                                 System.out.println(aff.toString());

System.out.println("duration: " + aff.getProperty("duration"));
                             }catch(Exception ex){
                                 ex.printStackTrace();
                             }
        

Open in new window


output:
m: {}
WAVE (.wav) file, byte length: 171100, data format: PCM_SIGNED 22050.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian, frame length: 42752
duration: null

Open in new window



Post your file - maybe we'll see duration there

Awarded 2011
Awarded 2011

Commented:
Unfortunately it does not support either .mid or .mp3 file - writes error - usnsupported  file type

perhpas we can make it recognize MP3 if download MP3 plugin of the JMF:

http://www.oracle.com/technetwork/java/javase/download-137625.html

Awarded 2011
Awarded 2011

Commented:
This is printout from your cartcar.wav

m: {}
WAVE (.wav) file, byte length: 71619, data format: PCM_UNSIGNED 22050.0 Hz, 8 bit, mono, 1 bytes/frame, , frame length: 71575
duration: null

Open in new window


so I guess duration would be 71575/22050 = 3.24 sec
Awarded 2011
Awarded 2011

Commented:
so at least for .wav files we can do it
Mike EghtebasDatabase and Application Developer

Author

Commented:
I just back. Thank you for all the work. I am using wav if it supports it. I am basically limited to mid or wav (the two I know java supports).

Although you started with c++ (which I know nothing about); but it seems in the last part your solutions are in java.

I am going through your post now.
Awarded 2011
Awarded 2011

Commented:
yes, c++ is tough way, although it should give more properties and for any kind of windows files

The Java is much more limited for now only to wav's and allows limited properties but at least works for two wav's that i tried
and looks like allows to find the duration

and with my file tada.wav less than 2 sec seems also reasonable though I could not see it in windows properties
Mike EghtebasDatabase and Application Developer

Author

Commented:
Now I am trying to copy your code piece to incorporate with what I have at:

     public void start() {
        t =3650; //<----*********
        timer.start();
        audioClip.play();
        play.setEnabled(false);
        stop.setEnabled(true);
        loop.setEnabled(true);          
    }
Mike EghtebasDatabase and Application Developer

Author

Commented:
I guess I need to import some additional package. I am having problem with:

AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("cartcar.wav"));
            Map<String, Object> m = aff.properties();

in:

    public void start() {
       
        try{
            AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("cartcar.wav"));
            Map<String, Object> m = aff.properties();
            System.out.println("m: " + m);

            System.out.println(aff.toString());

            System.out.println("duration: " + aff.getProperty("duration"));
        }catch(Exception ex){
            ex.printStackTrace();
        }  
       
        t =3650;
        timer.start();
        audioClip.play();
        play.setEnabled(false);
        stop.setEnabled(true);
        loop.setEnabled(true);          
    }

Also, in the to, I have file name entered. It will be nice somehow to use that, see:

    public Exercise18_20() {

        audioClip = Applet.newAudioClip(getClass().getResource("cartcar.wav"));
        JPanel pane = new JPanel(new FlowLayout());
Awarded 2011
Awarded 2011

Commented:


import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;

but it is part of standard java - my IDE recognized them automatically
Mike EghtebasDatabase and Application Developer

Author

Commented:
Thanks, that was good.

Now it is asking for File and Map classes used in
                                                                                       v--******
AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("cartcar.wav"));
            Map<String, Object> m = aff.properties();
              ^---*****
Mike EghtebasDatabase and Application Developer

Author

Commented:
it looks like:

AudioFileFormat aff = AudioSystem.getAudioFileFormat(getClass().getResource("cartcar.wav"));

working for File, in place of

                                                                                       v--******
AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("cartcar.wav"));
Awarded 2011
Awarded 2011

Commented:
You don't need anything actually about map - just
AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("cartcar.wav"));
and then to parse
aff.toString()
into two numbers and then divide one by anorther to get the seconds

Map contains noithing and is not useful in this case
Mike EghtebasDatabase and Application Developer

Author

Commented:
Now, method:  public void start()  works nicely except that I have to enter file name "cartcar.wav" two times. Once at:

    public Exercise18_20() {
        audioClip = Applet.newAudioClip(getClass().getResource("cartcar.wav"));

and once again at:

    public void start() {
        try{
//          AudioFileFormat aff = AudioSystem.getAudioFileFormat(audioClip)
            AudioFileFormat aff = AudioSystem.getAudioFileFormat(getClass().getResource("cartcar.wav"));


public void start() {
        
        try{
//          AudioFileFormat aff = AudioSystem.getAudioFileFormat(audioClip)
            AudioFileFormat aff = AudioSystem.getAudioFileFormat(getClass().getResource("cartcar.wav"));
            String[] temp = aff.toString().split(" ");
            t=(Integer.parseInt(temp[temp.length - 1])/22050)*1000;
            timer.start();
            audioClip.play();
            play.setEnabled(false);
            stop.setEnabled(true);
            loop.setEnabled(true);

        }catch(Exception ex){
            ex.printStackTrace();
        }  
        
          
    }

Open in new window

Awarded 2011
Awarded 2011

Commented:
You can introduce variable clipURL = getClass().getResource("cartcar.wav");
 and use it both times.
It does not actually matter