0

私は音楽ビジュアライザーを作成しており、mp3plugin ( http://pscode.org/lib/mp3plugin.jar ) を使用して Java で mp3 ファイルを再生しようとしています。しかし、おそらくこのプラグインを使用したり音楽をコーディングしたりする経験が不足しているため、エラーが発生しました。

私はこのコードをさまざまな mp3 ファイルでテストしましたが、すべて同じ問題がありました。mp3 ファイルに問題があることをある程度確信を持って除外できると思います。

以下の私のコード:

AudioInputStream audioIn;
try {
    JS_MP3FileReader m = new JS_MP3FileReader();
    audioIn = m.getAudioInputStream(new File(ex.trackname));
    //audioIn = AudioSystem.getAudioInputStream(new File(ex.trackname));
    // Get a sound clip resource.
    Clip clip = AudioSystem.getClip();
    // Open audio clip and load samples from the audio input stream.
    clip.open(audioIn);
    clip.start();
} catch (Exception e) {
    e.printStackTrace();
}

私が得るエラー:

javax.sound.sampled.LineUnavailableException: line with format MPEG1L3 48000.0 Hz, unknown bits per sample, stereo, unknown frame size, unknown frame rate,  not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(Unknown Source)
at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(Unknown Source)
at com.sun.media.sound.AbstractDataLine.open(Unknown Source)
at com.sun.media.sound.DirectAudioDevice$DirectClip.open(Unknown Source)
at com.sun.media.sound.DirectAudioDevice$DirectClip.open(Unknown Source)
at Logic.Run$1.run(Run.java:101)
at java.lang.Thread.run(Unknown Source)

(このコードを実行する私が作成したクラス インスタンスは Run と呼ばれることに注意してください)

プラグイン ファイルを含む、以下の私のプロジェクト構造:

プロジェクトの構造

4

1 に答える 1

1

JavaSound を直接使用して mp3 オーディオを再生していますが、非常にうまく機能します。

完全に機能するコードを次に示します (楽しんでください)。

package XXXXXXXXXXXXXX
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.*;


public class AudioPlayer
{
    private int bufferSize = 4096; // Tamanho de buffer padrão 4k
    private volatile boolean paused = false;
    private final Object lock = new Object();
    private SourceDataLine line;
    private int secondsFade = 0;
    private ArrayList<AudioPlayerListener> _listeners = new ArrayList<AudioPlayerListener>();

    public void stop()
    {
        if(line != null)
        {
            line.stop();
            line.close();
        }
    }

    public boolean isPaused()
    {
        return this.paused;
    }


    public void pause()
    {
        if(!this.isPaused())
            paused = true;
    }

    public void resume()
    {
        if(this.isPaused())
        {
            synchronized(lock){
                lock.notifyAll();
                paused = false;
            }
        }
    }

    public void play(File file) throws UnsupportedAudioFileException, IOException, LineUnavailableException, InterruptedException
    {
        AudioInputStream encoded = AudioSystem.getAudioInputStream(file);
        AudioFormat encodedFormat = encoded.getFormat();
        AudioFormat decodedFormat = this.getDecodedFormat(encodedFormat);
        Long duration = null;
        AudioInputStream currentDecoded = AudioSystem.getAudioInputStream(decodedFormat, encoded);
        line = AudioSystem.getSourceDataLine(decodedFormat);
        line.open(decodedFormat);
        line.start();
        boolean fezFadeIn = false;
        boolean fezFadeOut = false;
        byte[] b = new byte[this.bufferSize];
        int i = 0;
        Map properties = null;
        try 
        {
            properties = AudioUtil.getMetadata(file);
            duration = (Long) properties.get("duration");
        } 
        catch (Exception ex)
        {
            duration = 0L;
        }

        duration = duration < 0 ? 0 : duration;

        synchronized(lock)
        {
            //Parametro que ativa ou não o fade de acordo com o tamanho do áudio
            long paramFade = (secondsFade*2+1)*1000000;
            //long paramFade = 0;
            //Logger.getLogger(this.getClass().getName()).info("Arquivo: "+file+", DURACAO DO AUDIO: "+duration+", paramfade: "+paramFade);
            while(true)
            {
                if(secondsFade > 0 && !fezFadeIn && duration >= paramFade)
                {
                    fezFadeIn = true;
                    fadeInAsync(this.secondsFade);
                }

                if( secondsFade > 0 &&
                        duration > paramFade &&
                        !fezFadeOut &&
                        line.getMicrosecondPosition() >= duration - ((this.secondsFade+1)*1000000) )
                {
                    this.fireAboutToFinish();
                    fadeOutAsync(this.secondsFade);
                    fezFadeOut = true;
                }

                if(paused == true)
                {
                    line.stop();
                    lock.wait();
                    line.start();
                }

                i = currentDecoded.read(b, 0, b.length);
                if(i == -1)
                    break;

                line.write(b, 0, i);
            }
        }

        if(  !fezFadeOut && line.isOpen() )
            this.fireAboutToFinish();

        line.drain();
        line.stop();
        line.close();
        currentDecoded.close();
        encoded.close();
    }

    public synchronized void fadeInAsync(final int seconds)
    {
        if(line != null && line.isOpen())
        {
            Thread t = new Thread(new Fader(true, this, secondsFade));
            t.start();
        }
    }

    public synchronized void fadeOutAsync(final int seconds)
    {
        if(line != null && line.isOpen())
        {
            Thread t = new Thread(new Fader(false, this, secondsFade));
            t.start();            
        }
    }

    public void setVolume(double value) 
    {
        if(!line.isOpen())
            return;
        // value is between 0 and 1
        value = (value<=0.0)? 0.0001 : ((value>1.0)? 1.0 : value);
        try
        {
            float dB = (float)(Math.log(value)/Math.log(10.0)*20.0);
            ((FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN)).setValue(dB);
        }
        catch(Exception ex)
        {

        }
    }

    public boolean isPlaying()
    {
        return (line != null && line.isOpen());
    }


    protected AudioFormat getDecodedFormat(AudioFormat format)
    {
        AudioFormat decodedFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,  // Encoding to use
                format.getSampleRate(),           // sample rate (same as base format)
                16,               // sample size in bits (thx to Javazoom)
                format.getChannels(),             // # of Channels
                format.getChannels()*2,           // Frame Size
                format.getSampleRate(),           // Frame Rate
                false                 // Big Endian
        );
        return decodedFormat;    
    }


    public int getBufferSize()
    {
        return bufferSize;
    }


    public void setBufferSize(int bufferSize)
    {
        if(bufferSize <= 0)
            return;
        this.bufferSize = bufferSize;
    }

    /**
     * @return the secondsFade
     */
    public int getSecondsFade() {
        return secondsFade;
    }

    /**
     * @param secondsFade the secondsFade to set
     */
    public void setSecondsFade(int secondsFade) {
        if(secondsFade < 0 || secondsFade > 10)
            throw new IllegalArgumentException("Erro ao configurar cross-fade com valor em segundos: "+secondsFade);
        this.secondsFade = secondsFade;
    }

    public void addAudioPlayerListener(AudioPlayerListener a)
    {
        this._listeners.add(a);
    }

    public void removeAudioPlayerListener(AudioPlayerListener a)
    {
        this._listeners.remove(a);
    }

    private void fireAboutToFinish()
    {
        for(AudioPlayerListener a : this._listeners)
            a.aboutToFinish(this);
    }
}


class Fader implements Runnable
{
    private boolean fadeIn;
    private int seconds=0;
    private final AudioPlayer player;
    private float increaseParam;

    public Fader(boolean fadeIn, AudioPlayer player, int secondsToFade) 
    {
        this.fadeIn = fadeIn;
        this.seconds = secondsToFade;
        this.player = player;
        if(fadeIn)
            increaseParam = 0.01F;
        else
            increaseParam = -0.01F;
    }

    @Override
    public void run() 
    {
        try
        {
            encapsulateRun();
        }
        catch(Exception ex)
        {
            if(fadeIn)
                player.setVolume(1.0F);
            else
                player.setVolume(0.0F);
        }
    }

    private void encapsulateRun() throws Exception
    {
        synchronized(player)
        {            
            float per;
            if(fadeIn)
            {
                Logger.getLogger(getClass().getName()).info("Fazendo fade in");
                per = 0.0F;
            }
            else
            {
                Logger.getLogger(getClass().getName()).info("Fazendo fade out");
                per = 1.0F;
            }
            player.setVolume(per);
            if(fadeIn)
            {
                while(per < 1.00F)
                {
                    per = per + increaseParam;
                    player.setVolume(per);
                    Thread.sleep(10*seconds);
                }
            }
            else
            {
                while(per > 0.00F)
                {
                    per = per + increaseParam;
                    player.setVolume(per);
                    Thread.sleep(10*seconds);
                }
            }
        }
    }

}

また、mp3 のフェードインおよびフェードアウトもサポートしています。必要なのは、プロジェクトに 3 つの jar を追加することだけです。これらのバージョンでテストしました:

jl.1.0.1.jar (またはそれ以降) mp3spi1.9.5.jar (またはそれ以降)

http://www.javazoom.net/projects.htmlにあります

tritonus_share.jar

http://www.tritonus.org/にあります。

AudioUtil.java

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;
public class AudioUtil
{
    private static ArrayList<FileMap> cache = new ArrayList<FileMap>();
    private static int _CACHE_SIZE = 5;

    public static Map<String, Object> getMetadata(File filename) throws Exception
    {
        FileMap fm = new FileMap(filename, null);
        int index = cache.indexOf(fm);
        if(index >= 0)
            return cache.get(index).getMap();

        AudioFileFormat format = AudioSystem.getAudioFileFormat(filename);

        Map<String, Object> mapa = new HashMap<String, Object>();
        mapa.putAll(format.properties());


        if(mapa.get("author") == null && filename.getName().contains(" - "))
        {
            mapa = new HashMap<String, Object>();
            String[] s = filename.getName().split(" - ");
            mapa.put("author", s[0]);
            s[1] = s[1].substring(0, s[1].length()-4);
            mapa.put("title", s[1]);
        }

        if(mapa.get("author") == null)
        {
            mapa.put("author", "Desconhecido");
            mapa.put("title", "Desconhecido");
        }

        Object o = format.properties().get("duration");

        if(o == null)
            mapa.put("duration", 0);

        fm.setMap(mapa);
        cache.add(fm);
        while(cache.size() > _CACHE_SIZE)
            cache.remove((int)0);

        return mapa;
    }
}

class FileMap
{
    private File file;
    private Map<String, Object> map;

    public FileMap(File file, Map<String, Object> map) 
    {
        this.file = file;
        this.map = map;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public Map<String, Object> getMap() {
        return map;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }

    @Override
    public boolean equals(Object obj) 
    {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FileMap other = (FileMap) obj;
        if (this.file != other.file && (this.file == null || !this.file.equals(other.file))) 
        {
            return false;
        }
        return true;
    }

}
于 2013-02-19T14:25:23.293 に答える