【问题标题】:JavaSound: Extract one channel of stereo audioJavaSound:提取一声道立体声音频
【发布时间】:2020-06-03 04:43:56
【问题描述】:

我有一个立体声文件,我只需要读取和播放选定的频道。实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: java audio javasound


    【解决方案1】:

    当您通过 AudioInputStream 引入 wav 文件时,使用 AudioFileFormat 信息将字节转换为 PCM。左右的数据交替出现。因此,如果该行是 16 位,则每帧将有 4 个字节。前两个将组装到左通道中,后两个将组装到右通道中。 (或者反之亦然——我很难记住哪个频道是左还是右。)

    这是一个很好的教程,其中包含有关如何阅读一行的示例: http://docs.oracle.com/javase/tutorial/sound/converters.html

    可能需要跟踪中的一些早期教程来帮助澄清。此外,如果您对将字节转换为 PCM 和返回有疑问,StackOverflow 上已有一些解释可供参考。应该不难找到它们。

    【讨论】:

    • 谢谢菲尔!现在查看教程。
    • 您能否详细说明“转换为 DSP”?
    • 那是我的心理毛球。我应该说PCM!对于那个很抱歉。我更正了原帖。
    • 4 字节帧中的字节 0 和 1 是左声道。感谢您的帮助!
    【解决方案2】:

    这是一个从多声道直接音频线 (JavaSound) 中提取单声道的简单方法。用我的 Line6(r) Helix(r) 吉他音效板(8 通道)试了一下,效果很好。我猜它适用于任何类型的 DataTargetLine。在这种情况下,我们基于包含 16 位样本的 AudioFormat 处理数据。希望对您有所帮助。

        public ArrayList<byte[]> extract16BitsSingleChannels(byte[] audioBuffer, int channels) {
    
        /* Parameters :
         * 
         * audioBuffer : the buffer that has just been produced by
         * your targetDataLine.read();
         * channels : the number of channels defined in the AudioFormat you 
         * use with the line
         * 
         *  the AudioFormat which I tested :
         *       float sampleRate = 44100; 
         *       int sampleSizeInBits = 16;
         *       int channels = 8;
         *       boolean signed = true;
         *       boolean bigEndian = true;
         */
    
    
        /* let's create a container which will receive our "per channel" buffers */
    
        ArrayList<byte[]> channelsData = new ArrayList<byte[]>();
    
        /* take care of adjusting the size of the audioBuffer so that 
         * audioBuffer % channels == 0 is true ... because :        
         */
    
        final int channelLength=audioBuffer.length/channels;
    
        /* let's create one buffer per channel and place them in the
         * container 
         */
    
        for (int c=0 ; c < channels ; c++) 
    
        {
            byte[] channel=new byte[channelLength];
            channelsData.add(channel);
        }
    
        /* then process bytes from audioBuffer and copy each channels byte 
         * in its dedicated buffer 
         */
    
        int byteIndex=0; 
    
        for(int i = 0; i < channelLength; i+=2) //i+=2 for 16 bits=2 Bytes samples
        {
            for (int c=0 ; c < channels ; c++) {
                channelsData.get(c)[i]=audioBuffer[byteIndex];   // 1st Byte
                byteIndex++;
                channelsData.get(c)[i+1]=audioBuffer[byteIndex]; // 2nd Byte
                byteIndex++;
            }
    
        }
    
        /* Returns each set of bytes from each channel in its buffer you can use to
           write on whatever Byte streamer you like. */
    
        return channelsData;   
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-22
      • 2015-12-27
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多