不需要的下采样:Java声音

不需要的下采样:Java声音,java,javasound,Java,Javasound,我一直在尝试手动读取Java中的wav文件,读取字节数组,然后写入音频缓冲区进行播放。我正在接收回放,但它严重失真。Java声音支持16位采样率,但不支持24位采样率 我进入逻辑9,将一个24位音频文件导出到16位,然后与我的程序一起使用。最初,24位采样将产生白噪声。现在我可以听到我的样本,但非常失真,听起来像是被压碎了 有人能帮我得到一个干净的信号吗 我对音频编程非常陌生,但我目前正在一个基本的数字音频工作站上工作 import javax.sound.sampled.*; import j

我一直在尝试手动读取Java中的wav文件,读取字节数组,然后写入音频缓冲区进行播放。我正在接收回放,但它严重失真。Java声音支持16位采样率,但不支持24位采样率

我进入逻辑9,将一个24位音频文件导出到16位,然后与我的程序一起使用。最初,24位采样将产生白噪声。现在我可以听到我的样本,但非常失真,听起来像是被压碎了

有人能帮我得到一个干净的信号吗

我对音频编程非常陌生,但我目前正在一个基本的数字音频工作站上工作

import javax.sound.sampled.*;
import javax.sound.sampled.DataLine.Info;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;

public class AudioData {

    private String filepath;
    private String filepath1;
    private File file;
    private byte [] fileContent;
    private Mixer mixer;
    private Mixer.Info[] mixInfos;
    private AudioInputStream input;
    private ByteArrayOutputStream byteoutput;

    public static void main (String [] args) {
        AudioData audiodata = new AudioData();
    }

    public AudioData () {
        filepath = "/Users/ivaannagen/Documents/Samples/Engineering Samples - Obscure Techno Vol 3 (WAV)/ES_OT3_Kit03_Gmin_130bpm/ES_OT3_Kit03_FX_Fast_Snare_Riser_Gmin_130bpm.wav";
        filepath1 = "/Users/ivaannagen/Documents/Samples/dawsampletest.wav";
        file = new File (filepath1);
        readAudio();
    }

    public void readAudio () {
        mixInfos = AudioSystem.getMixerInfo();

        mixer = AudioSystem.getMixer(mixInfos[0]);

        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
        // set up an audio format.

        try {
            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); // creates data line with class type and audio format.
            SourceDataLine source = (SourceDataLine) AudioSystem.getLine(info);

           System.out.println("Size of data line buffer: " + source.getBufferSize());

            fileContent = new byte [source.getBufferSize() / 50];

            byteoutput = new ByteArrayOutputStream();
            input = AudioSystem.getAudioInputStream(file);

            int readBytes = 0;
            while ((readBytes = input.read(fileContent, 0, fileContent.length)) != -1) {
                byteoutput.write(fileContent, 0, readBytes);
            }
            System.out.println("Size of audio buffer: " + fileContent.length);

            //byteoutput.write(0);
          //  byteoutput.write(0);

            System.out.println("Size of audio buffer: " + byteoutput.size());

            source.open(format, source.getBufferSize());   // line must be open to be recognised by the mixer.

            Line[] lines = mixer.getSourceLines();

            System.out.println("mixer lines: " + lines.length);

           // for(byte bytes: fileContent) {
               // System.out.println(bytes);
          //  }

            Thread playback = new Thread () {
                public void run () {
                   // System.out.println((byteoutput.size() +2) % 4);
                        source.start();    // play (buffer originally empty)
                        source.write(byteoutput.toByteArray(), 0, byteoutput.size());  // write input bytes to output buffer
                }  // end run (to do).
            };  // end thread action

            playback.start(); // start thread
        }
        catch (LineUnavailableException lue) {
            System.out.println(lue.getMessage());
        }
        catch (FileNotFoundException fnfe) {
            System.out.println(fnfe.getMessage());
        }
        catch(IOException ioe) {
            System.out.println(ioe.getMessage());
        }
        catch(UnsupportedAudioFileException uafe) {
            System.out.println(uafe.getMessage());
        }
    }
}

能否加载和播放24位文件取决于系统,afaik

我用无畏来转换。您应该能够将文件导入Audacity并将其导出为16位、立体声、小尾端、44100 fps,然后使用Java的
AudioInputStream
加载导出

从Audacity或Java播放时听到的内容应该非常相同(根据音量进行调整)。如果不是,最可能的原因可能与代码中的错误或疏忽有关,这很容易做到

在代码中使用
字节输出流是多余的。从
AudioInputStream
读取固定大小的字节数组(大小为缓冲区长度,我建议第一次尝试使用8或16*1024字节),然后使用
SourceDataLine
write方法发送该数组

下面是在我的系统上运行的代码,用于加载一个名为“a3.wav”的“CD质量”wav,该wav与Java类位于同一目录中。你应该能够在你自己的44100,16位,立体声,小endian wav文件交换

我已经注释掉了加载和播放一个名为“spoken8000_24.wav”的24位wav文件的尝试。那次尝试给了我一个
IllegalArgumentException
无线路匹配接口源数据线支持格式PCM\u签名8000.0 Hz,24位,立体声,6字节/帧,支持little-endian。

我必须承认,我不清楚我的系统是否没有提供所需的行,或者我是否可能错误地编码了格式!我的操作系统当然可以播放该文件。因此,我认为操作系统的功能与给定系统上的“混合器”为Java提供的功能之间存在区别

作为一种权宜之计,我总是将所有内容转换为“CD质量”格式,因为这似乎是最广泛支持的格式

public class TriggerSound_SDL extends JFrame
{
    public TriggerSound_SDL()
    {
        JButton button = new JButton("Play Sound");
        button.addActionListener(e -> new Thread(() -> playBuzzer()).start());
        getContentPane().add(button);
    }

    private void playBuzzer()
    {
        try 
        {
            URL url;
            url = getClass().getResource("a3.wav");
//          url = getClass().getResource("spoken8000_24.wav");
            AudioInputStream ais = AudioSystem.getAudioInputStream(url); 
            System.out.println(ais.getFormat());

            AudioFormat audioFmt;
            // "CD Quality" 44100 fps, 16-bit, stereo, little endian
            audioFmt = new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED, 
                    44100, 16, 2, 4, 44100, false);

            // 8000 fps, 32-bit, stereo
//          audioFmt = new AudioFormat(
//                  AudioFormat.Encoding.PCM_SIGNED, 
//                  8000, 24, 2, 6, 8000, false);

            Info info = new DataLine.Info(SourceDataLine.class, 
                    audioFmt);
            SourceDataLine sdl = (SourceDataLine)AudioSystem.getLine(info);
            int bufferSize = 16 * 1024;
            byte[] buffer = new byte[bufferSize];
            sdl.open(audioFmt, bufferSize);
            sdl.start();

            int numBytesRead = 0;

            while((numBytesRead = ais.read(buffer)) != -1)
            {
                sdl.write(buffer, 0, numBytesRead);
            }
        }
        catch (IOException | UnsupportedAudioFileException 
                | LineUnavailableException ex)
        {
            ex.printStackTrace();
        }       
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new TriggerSound_SDL();
        frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }
}
这段代码,加上一些小的调整,至少可以让你测试不同的格式

编辑: 我在看你的目标是什么!
在这种情况下,您需要将字节转换为PCM数据。我可以建议你向我借一些代码吗?我写它基本上是为了一个剪辑的替代品,其中一部分涉及到使PCM数据可用于操作。可以在其中找到一些混合、以不同频率播放和多线程的技术。

谢谢大家的建议。我将摆脱字节输出流,只使用音频输入流,我现在明白我所做的是不必要的!!谢谢大家的建议!我确实尝试过使用AudioCue,但对于我想做的事情来说,它的级别还不够低

还有一件事,伙计们。之前,我创建了一个使用Clip类的多轨媒体播放器。为了一起播放所有的音轨,我循环播放了一系列剪辑。然而,这意味着由于循环的处理,所有曲目可能会在彼此之后播放少量。另外,Clip类为每个音频创建了一个新线程。我不希望100个线程在100首曲目上运行,我希望我的音频输出有一个线程。我仍在努力解决如何在没有循环的情况下同时启动所有曲目…(我猜AudioCue已经锁定了并发提示)

有人知道在一个输出中播放多个音轨的最佳方法吗?我是否需要将所有音频曲目路由/总线到一个输出,并将音频文件中的所有数据写入一个输出缓冲区,然后在线程中播放该输出


谢谢

新的音频格式(AudioFormat.Encoding.PCM_SIGNED,44100,16,2,4,44100,false)为什么要假定格式,而不是从加载的声音中获取信息?现在,我希望看到一切正常。Javasound只支持wav文件,我还没有研究过支持mp3等。我相信JavaFX audio对mp3有一些支持,但我还没有尝试过。“Javasound只支持wav文件”请参阅。SPI可以支持其他格式。一个是MP3@Philfreihoff“我相信JavaFX音频对mp3有一些支持”是的。我为javafx的媒体播放器更改了我的javasound+mp3spi&它似乎可以播放我所有的MP3。声音和视频媒体的JavaFX接口非常高级,因此不支持对声音流本身的访问(AFAIU-crudely)。虽然你可以得到光谱!同意高水平。在编写AudioCue时,我对它进行了一些研究,但得到的印象是,虽然JavaFX中的Clip有一些改进,但对于我的目的来说,它的级别太高了。我想知道他们是否编写了一个全新的子系统,或者是否采用了一些java.sound。我还没有深入了解。我认为支持的内容可能有所不同。javax.sound.sampled应该对.wav之外的其他类型有一些规定,但我从来没有使用它们的理由,也没有探讨过这方面。好的,请参阅下面的消息,但感谢您的所有建议。我来看看我能从音频提示中得到什么。当然,我现在这样做是转换字节以进行音量和频率控制等的最佳方式,因为我有一个原始数据数组?当你说将字节转换为PCM数据时,你是什么意思?这是用来导出曲目的吗?所以,一旦我的音频被处理,我就可以将字节数组导出回.wav文件了?这就是你的意思吗?PCM是脉冲编码调制。这一术语常用于co