-1

This is the code I have as of now:

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.util.Scanner;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.sampled.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

public class changeyouvoice extends Frame implements WindowListener, ActionListener {
    JButton upload;
    JFileChooser jfc;
    int i;
    Long currentFrame;
    Clip clip;
    String status;

    public static void main(String[] args) {
        // 2nd step
        changeyouvoice myWindow = new changeyouvoice();
        myWindow.setSize(350, 100);
        myWindow.setVisible(true);
    }

    public changeyouvoice() {
        jfc = new JFileChooser();
        setLayout(new FlowLayout());
        addWindowListener(this);
        upload = new JButton("Upload");
        add(upload);
        upload.addActionListener(this);
        // create AudioInputStream object
    }

    public void actionPerformed(ActionEvent e) {
        jfc.setDialogTitle("Select the video of your voice");
        jfc.setAcceptAllFileFilterUsed(false);// you are not searching for anything.
        // figure out why
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Select Audio", "m4a", "mp3", "flac", "wav", "wma",
                "aac");
        jfc.setFileFilter(filter);
        int returnValue = jfc.showOpenDialog(this);
        // create AudioInputStream object
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            try {
                if (e.getSource() == upload) {
                    int x = jfc.showOpenDialog(this);
                    if (x == JFileChooser.APPROVE_OPTION) {
                        File fileToBeSent = jfc.getSelectedFile();
                        File initialFile = new File(fileToBeSent.getAbsolutePath());
                        try {
                            // InputStream targetStream;
                            InputStream targetStream = new FileInputStream(initialFile);
                            AudioInputStream myvoice = AudioSystem.getAudioInputStream(targetStream); // figure
                                                                                                      // out
                                                                                                      // how
                                                                                                      // its
                            // created. read the file
                            // and get audio stream
                            // create AudioInputStream object
                            // create clip reference
                            clip = AudioSystem.getClip();
                            try {
                                clip.start();
                                clip.open(myvoice);
                                clip.loop(Clip.LOOP_CONTINUOUSLY);
                                status = "play";
                                Scanner sc = new Scanner(System.in);

                                while (true) {
                                    System.out.println("1. pause");
                                    System.out.println("2. resume");
                                    System.out.println("3. restart");
                                    System.out.println("4. stop");
                                    System.out.println("5. Jump to specific time");
                                    int c = sc.nextInt();
                                    switch (c) {
                                        case 1:
                                            pause();
                                            break;
                                        case 2:
                                            resumeAudio();
                                            break;
                                        case 3:
                                            restart();
                                            break;
                                        case 4:
                                            stop();
                                            break;
                                        case 5:
                                            System.out.println("Enter time (" + 0 +
                                                    ", " + clip.getMicrosecondLength() + ")");
                                            long c1 = sc.nextLong();
                                            jump(c1);
                                            break;
                                    }
                                    if (c == 4)
                                        break;
                                }
                                sc.close();
                            } catch (Exception ex) {
                                System.out.println("Error with playing sound.");
                                ex.printStackTrace();
                            }
                            // create clip reference
                            // open audioInputStream to the clip
                        } catch (Exception j) {
                            // Handle the error...
                            System.out.println(j.toString());
                        }
                    }
                }
            } catch (Exception png) {
                // Handle the error...
                System.out.println(png.toString());
            } finally {
                // ... cleanup that will execute whether or not an error occurred ...
            }
        }
    }

    // Method to pause the audio
    public void pause() {
        if (status.equals("paused")) {
            System.out.println("audio is already paused");
            return;
        }
        this.currentFrame = this.clip.getMicrosecondPosition();
        clip.stop();
        status = "paused";
    }

    // Method to resume the audio
    public void resumeAudio() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        if (status.equals("play")) {
            System.out.println("Audio is already " + "being played");
            return;
        }
        clip.close();
        resetAudioStream();
        clip.setMicrosecondPosition(currentFrame);
        clip.start();
        status = "play";
    }

    // Method to restart the audio
    public void restart() throws IOException, LineUnavailableException, UnsupportedAudioFileException {
        clip.stop();
        clip.close();
        resetAudioStream();
        currentFrame = 0L;
        clip.setMicrosecondPosition(0);
        clip.start();
        status = "play";
    }

    // Method to stop the audio
    public void stop() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        currentFrame = 0L;
        clip.stop();
        clip.close();
    }

    // Method to jump over a specific part
    public void jump(long c) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        if (c > 0 && c < clip.getMicrosecondLength()) {
            clip.stop();
            clip.close();
            resetAudioStream();
            currentFrame = c;
            clip.setMicrosecondPosition(c);
            clip.start();
            status = "play";
        }
    }

    // Method to reset audio stream
    public void resetAudioStream() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        AudioInputStream audioInputStream = AudioSystem
                .getAudioInputStream(this.getClass().getResource(jfc.getSelectedFile().getAbsolutePath()));
        clip.open(audioInputStream);
        clip.loop(Clip.LOOP_CONTINUOUSLY);
    }

    public void windowClosing(WindowEvent e) {
        dispose();
        System.exit(0);
    }

    public void windowOpened(WindowEvent e) {
    }

    public void windowActivated(WindowEvent e) {
    }

    public void windowIconified(WindowEvent e) {
    }

    public void windowDeiconified(WindowEvent e) {
    }

    public void windowDeactivated(WindowEvent e) {
    }

    public void windowClosed(WindowEvent e) {
    }
}

The code works fine when uploading a file, but for some reason I am not able to play, pause, or resume the audio. I used several tutorials to get the functions to help play the audio, but when I uploaded the file I had to upload it twice and an exception was displayed which was

/Users/thevladimirgeorge/Downloads/Vlad's story.mp3
java.io.IOException: mark/reset not supported

I wonder what was the issue going on with the code. The app I used to code is Visual Studio Code.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433

1 Answers1

1

If you provide a URL instead of an InputStream as an argument to AudioSystem.getAudioStream, the requirement that the media resource supports marking and resetting is circumvented. This can be observed by comparing the APIs for the two methods.

AudioSystem.getAudioInputStream(InputStream)

AudioSystem.getAudioInputStream(URL)

Only the method that takes InputStream includes these checks:

The implementation of this method may require multiple parsers to examine the stream to determine whether they support it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and reset the stream's read pointer to its original position. If the input stream does not support these operations, this method may fail with an IOException.

So, rewriting the code to obtain a URL for your resource instead of an InputStream should solve your problem, unless you explicitly need to have the AudioInputStream support marking and resetting. I've not come across such a scenario myself. Would be interesting in learning about situations where this capability is used.

EDIT: I overlooked that you are trying to load an mp3. Java doesn't directly support this or many of the other files on your list of audio. You will need to include additional libraries and code to handle these. The following (executed in jshell) can show what formats are supported:

jshell> import javax.sound.sampled.*;
jshell> AudioFileFormat.Type[] types = AudioSystem.getAudioFileTypes();
types ==> AudioFileFormat$Type[3] { WAVE, AU, AIFF }

More documentation can be found in the JavaSound section of the TroubleShooting Guide.

Phil Freihofner
  • 7,645
  • 1
  • 20
  • 41
  • I tried that, thanks for your help! I really appreciate your efforts. The code I replaced with was ```InputStream targetStream = new FileInputStream(initialFile);``` with ```URL url = initialFile.toURI().toURL();```, replacing the next line's input (in ()) with url. But the error I received was ```javax.sound.sampled.UnsupportedAudioFileException: URL of unsupported format```. – Vladimir George Jun 18 '22 at 07:12
  • Update: I got it to work when using an AIFF file. The file I originally uploaded was a MP3. – Vladimir George Jun 18 '22 at 07:20
  • That makes sense. Java does not support .mp3. I'm glad you were able to get your code to work. – Phil Freihofner Jun 18 '22 at 07:31