【问题标题】:How to get panning control forma a .mp3 file?如何获取.mp3 文件的平移控制格式?
【发布时间】:2018-12-23 08:07:22
【问题描述】:

我正在学习如何在 Java 中播放声音,但要使用高级控件。

我发现了一个问题:javax.sound.sampled.AudioInputStream 不支持 Mp3 文件,而且我找不到如何控制平移的想法。

我设法使用 javazoom.jl.player.advanced.AdvancedPlayer 播放了一个 Mp3 文件,但它没有平移控件,或者我没有创建它。

我的实际代码打开一个文件,如果格式与AudioInputStream兼容,它只播放正确的通道。如果格式不正确,则使用 AdvancedPlayer 播放。

您知道一种对 mp3 文件进行平移控制的方法吗?

我的代码在这里:

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;

import javax.sound.sampled.*;
import javax.swing.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class AudioPlayerExample2 {
    private static final int BUFFER_SIZE = 4096;

    public static void main(String[] args) throws IOException, LineUnavailableException, JavaLayerException {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.showOpenDialog(null);

        new AudioPlayerExample2().play(fileChooser.getSelectedFile());
    }


    void play(File file) throws IOException, LineUnavailableException, JavaLayerException {


        AudioInputStream audioStream;

        try {
            audioStream = AudioSystem.getAudioInputStream(file);

            AudioFormat format = audioStream.getFormat();
            System.err.println(format.toString());

            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

            SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);

            audioLine.open(format);

            audioLine.start();

            FloatControl pan = (FloatControl) audioLine.getControl(FloatControl.Type.PAN);

            byte[] bytesBuffer = new byte[BUFFER_SIZE];
            int bytesRead = -1;


            while ((bytesRead = audioStream.read(bytesBuffer)) != -1) {
                pan.setValue((float) (1));
                audioLine.write(bytesBuffer, 0, bytesRead);
            }

            audioLine.drain();
            audioLine.close();
            audioStream.close();
        } catch (UnsupportedAudioFileException e) {
            FileInputStream fis = new FileInputStream(file);
            AdvancedPlayer player = new AdvancedPlayer(fis);

            player.play();
        }


    }
}

【问题讨论】:

标签: java mp3 javasound panning


【解决方案1】:

声像和音量控制取决于系统,即使它们到位,有时也会有点不稳定。例如,如果您一次过多地更改音量或声相设置,不连续性会导致点击。

一种解决方案是逐帧进入其中并自己进行更改。例如,请参阅教程末尾的“直接操作音频数据”Processing Audio with Controls

例如,查看下一个教程中的代码:Using Files and Format Converters。在“Reading Sound Files”标题下查找代码中的注释“\ Here, do something useful...”

我邀请您也看看我编写并提供的代码,一个名为AudioCue 的类,它具有实时平移以及实时音量和音高播放控制。我添加了平滑(1024 步用于平移更改)以帮助减少不连续的可能性。

您可以将 mp3 文件解码为音频数据数组。我认为 github 上提供的 javazoom 库应该为您提供足够的代码访问权限来弄清楚如何执行此操作(我这样做是为了 ogg/vorbis 解码)。一旦你有了一个音频数据的浮点数组(立体声,从 -1 到 1 的有符号浮点数),就可以直接将其加载到 AudioCue 中。

【讨论】:

    【解决方案2】:

    首先,感谢 Andrew Thompson 和 Phil Freihofner,我很高兴能成为这个社区的一员并有一个值得信赖的人。你真的很开心:)

    我在这里留下完全符合我要求的完整代码。

    正如 JavaZoom MP3 SPI 文档所说:确保 JLayer、Tritonus 和 MP3SPI 库在您的 CLASSPATH 中可用。

    import javax.sound.sampled.*;
    import javax.swing.*;
    import java.io.File;
    import java.io.IOException;
    
    public class Test {
        public static void main(String[] args) throws IOException, 
    UnsupportedAudioFileException, LineUnavailableException {
        JFileChooser chooser = new JFileChooser();
        chooser.showOpenDialog(null);
        String path = chooser.getSelectedFile().getAbsolutePath();
    
        System.err.println(path);
        File file = new File(path);
    
        AudioInputStream baseStream = AudioSystem.getAudioInputStream(file);
    
        AudioFormat baseFormat = baseStream.getFormat();
    
        System.err.println(baseFormat.toString());
        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 
    baseFormat.getSampleRate(),
                16, baseFormat.getChannels(), baseFormat.getChannels() * 2, 
    baseFormat.getSampleRate(), true);
    
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
    
        AudioInputStream stream = AudioSystem.getAudioInputStream(format, baseStream);
    
        SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);
    
    
        audioLine.open(format);
        audioLine.start();
    
        FloatControl pan = (FloatControl) audioLine.getControl(FloatControl.Type.PAN);
    
        pan.setValue(1);
    
        int BUFFER_SIZE = 4096;
    
        byte[] buffer = new byte[BUFFER_SIZE];
    
        int read = -1;
    
        while((read = stream.read(buffer)) != -1){
            audioLine.write(buffer, 0, read);
        }
    
        audioLine.drain();
        audioLine.close();
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多