Java gets the sampling rate SampleRate of the Wav file

System: Win10
Java: 1.8.0_333
IDEA: 2020.3.4

1. Functional requirements

In the process of a project, I need to get the sampling rate (SampleRate) of the wav file. Later, I searched the Internet for tutorials and code samples and found that the codes on the Internet are the same. They all use the bit offset method to obtain the value. This method seems to be There is a bug. When the sampling rate is 44100Hz, the obtained value is a negative number. Later, after continuous searching and learning, this problem was finally solved.

2. Solutions

Several test audio files are used here, which have been uploaded to the resource file, and 0 point download is set. If you are interested, you can download it and test it
https://download.csdn.net/download/qq_35132089/86723016

2.1 Scheme 1

2.1.1 Code example

Here is to read the value of the corresponding position of the header file of the wav file and then convert the value

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

public class WavParsing {
    
    
    public static void main(String[] args) throws Exception {
    
    
        List<String> list = new ArrayList();
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\a.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\b.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\c.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\d.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\e.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\f.wav");
        for (String path : list) {
    
    
            File file = new File(path);
            RandomAccessFile rdf = null;
            /**
             * "r": 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
             * "rw": 打开以便读取和写入。
             * "rws": 打开以便读取和写入。相对于 "rw","rws" 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
             * "rwd" : 打开以便读取和写入,相对于 "rw","rwd" 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。
             */
            rdf = new RandomAccessFile(file, "r");
            System.out.println(file.getName() + " SampleRate:" + toInt(read(rdf)));  // 采样率、音频采样级别 8000 = 8KHz
            rdf.close();
        }
    }

    public static int toInt(byte[] b) {
    
    
        return u(b[15]) * 16777216 + u(b[14]) * 65536 + u(b[13]) * 256 + u(b[12]);
    }

    private static int u(int n) {
    
    
        return n & 255;
    }

    public static byte[] read(RandomAccessFile rdf) throws IOException {
    
    
        byte[] bytes = new byte[12];
        rdf.read(bytes);
        bytes = new byte[24];
        rdf.read(bytes);
        rdf.close();
        return bytes;
    }
}

2.1.2 Effect Demonstration

Run the test here and find that the obtained sampling rate is correct
insert image description here

2.2 Scheme 2

2.2.1 Code example

There is also a relatively simple method, which is to use the wheels that have been built by others. Many predecessors have written corresponding implementation functions for these corresponding methods. We only need to import the corresponding jar package to directly call the corresponding method. The advantage of using this method is that you can also call its encapsulated method to obtain other data such as duration, format, channel, etc. First, you need to
import the corresponding jar package. I use the maven project here, so import its corresponding dependencies.

<!-- 获取音频信息 -->
<dependency>
    <groupId>org</groupId>
    <artifactId>jaudiotagger</artifactId>
    <version>2.0.3</version>
</dependency>

test code

import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.wav.WavFileReader;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class AudioWavUtils {
    
    

    public static void main(String[] args) throws Exception {
    
    
        List<String> list = new ArrayList();
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\a.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\b.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\c.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\d.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\e.wav");
        list.add("C:\\Users\\Li\\Desktop\\WavResource\\f.wav");
        for (String path : list) {
    
    
            WavFileReader fileReader = new WavFileReader();
            AudioFile audioFile = fileReader.read(new File(path));
            System.out.println(audioFile.getFile().getName() + " SampleRate:" + audioFile.getAudioHeader().getSampleRate());
        }
    }
}

2.2.2 Effect Demonstration

Run it here and find that the sampling rate can be obtained normally
insert image description here

3. Analysis and summary

This problem took me about half a day to solve. The reason is that I first tested the code shared on the Internet, and the result was a negative number. I thought there was a problem with the code or the audio; then I started from the code. At the level of consideration, a lot of detours have been taken here, because I don't know much about the structure of audio files.
Later, I kept searching for information and found that the codes written by everyone are like this

public static int toInt(byte[] b) {
    
    
	return ((b[3] << 24) + (b[2] << 16) + (b[1] << 8) + (b[0] << 0));
}

public static short toShort(byte[] b) {
    
    
	return (short)((b[1] << 8) + (b[0] << 0));
}


public static byte[] read(RandomAccessFile rdf, int pos, int length) throws IOException {
    
    
	rdf.seek(pos);
	byte result[] = new byte[length];
	for (int i = 0; i < length; i++) {
    
    
		result[i] = rdf.readByte();
	}
	return result;
}

Later, after a period of invalid testing, I tried to change to a few samples with a smaller sampling rate, because I saw that the shift operator was used here, and I thought that the negative number might be caused by the value range. So when I changed the sampling rate to a small one and the test was successful, I knew that this might be the loophole in this code. So why is everyone writing like this? ?
I read the date of the article, 2011, I think it is the progress of the times, the development of audio, which has led to the increase of the sampling rate of the audio used now, and a large part of the article is copied directly, not even Test it, it's just a mistake.
However, the first batch of seniors who wrote that article must be correct. The times are advancing, and technology is also updated and iterated. A piece of code cannot maintain its effectiveness forever. What we need to learn from it is the idea of ​​​​solving the problem.

Guess you like

Origin blog.csdn.net/qq_35132089/article/details/127064902