欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用LAME,把PCM编码格式的录音文件转换为MP3格式的文件

程序员文章站 2022-06-21 15:06:37
...

最近,项目需要把PCM编码的录音文件转为MP3格式。
通过学习,发现可以使用de.sciss.jump3r项目:

        <dependency>
            <groupId>de.sciss</groupId>
            <artifactId>jump3r</artifactId>
            <version>1.0.5</version>
        </dependency>

测试代码:

public class LameTest {
    private static Logger LOG = LoggerFactory.getLogger(LameTest.class);

    @Test
    public void encode() {
        LameEncoder encoder = null;
        try {
            byte[] pcm = Files.readAllBytes(Paths.get("recordFiles/", "20190415_09_0016.wav"));

            int r = ThreadLocalRandom.current().nextInt(1000);
            Path file = Files.createFile(Paths.get("recordFiles/", "file_" + r + ".mp3"));

            AudioFormat format = fileFormat(pcm);
            encoder = new LameEncoder(format);

            byte[] buffer = new byte[encoder.getPCMBufferSize()];

            int bytesToTransfer = Math.min(buffer.length, pcm.length);
            int bytesWritten;
            int currentPcmPosition = 0;
            while (0 < (bytesWritten = encoder.encodeBuffer(pcm, currentPcmPosition, bytesToTransfer, buffer))) {
                currentPcmPosition += bytesToTransfer;
                bytesToTransfer = Math.min(buffer.length, pcm.length - currentPcmPosition);

                Files.write(file, copyOfRange(buffer, 0, bytesWritten), StandardOpenOption.APPEND);
            }

            LOG.info("new file is {}.", file.getFileName());
        } catch (IOException ex) {
            LOG.warn("encode error: {}.", ex);
        } finally {
            encoder.close();
        }
    }

}

wav文件头处理类:

public class WavFileUtil {
    private static Logger LOG = LoggerFactory.getLogger(WavFileUtil.class);

    private static final int HEAD_LENGTH = 12;

    private static final int FORMAT_LENGTH = 24;

    private static boolean isWav(byte[] head) {
        return ("RIFF".equals(new String(head, 0, 4, ISO_8859_1)) &&
                "WAVE".equals(new String(head, 8, 4, ISO_8859_1)));
    }

    private static void fileTooSmall(byte[] file) {
        if (file.length < HEAD_LENGTH + FORMAT_LENGTH) {
            LOG.warn("file is too small, size if {}.", file.length);
            throw new IvcFileException();
        }
    }

    public static int fileSize(byte[] file) {
        fileTooSmall(file);

        byte[] head = copyOfRange(file, 0, HEAD_LENGTH);

        if (isWav(head)) {
            return ByteBuffer.wrap(copyOfRange(head, 4, 8))
                    .order(LITTLE_ENDIAN)
                    .getInt() + 8;
        } else {
            LOG.warn("file format error: expected {}, actual {}.",
                    "[82, 73, 70, 70, *, *, *, *, 87, 65, 86, 69]",
                    head);
            throw new IvcFileException();
        }
    }

    public static AudioFormat fileFormat(byte[] file) {
        fileTooSmall(file);

        byte[] head = copyOfRange(file, 0, HEAD_LENGTH);

        if (isWav(head)) {
            byte[] format = copyOfRange(file, 12, HEAD_LENGTH + FORMAT_LENGTH);
            String chuckID = new String(format, 0, 4, ISO_8859_1);
            int chunkSize = ByteBuffer.wrap(copyOfRange(format, 4, 8))
                    .order(LITTLE_ENDIAN).getInt();
            int audioFmt = ByteBuffer.wrap(copyOfRange(format, 8, 10))
                    .order(LITTLE_ENDIAN).getShort();
            int channels = ByteBuffer.wrap(copyOfRange(format, 10, 12))
                    .order(LITTLE_ENDIAN).getShort();
            int sampleRate = ByteBuffer.wrap(copyOfRange(format, 12, 16))
                    .order(LITTLE_ENDIAN).getInt();
            int byteRate = ByteBuffer.wrap(copyOfRange(format, 16, 20))
                    .order(LITTLE_ENDIAN).getInt();
            int frameSize = ByteBuffer.wrap(copyOfRange(format, 20, 22))
                    .order(LITTLE_ENDIAN).getShort();
            int sampleSizeInBits = ByteBuffer.wrap(copyOfRange(format, 22, 24))
                    .order(LITTLE_ENDIAN).getShort();

            //return new AudioFormat(PCM_SIGNED, sampleRate,
            //        sampleSizeInBits, channels, frameSize, sampleRate, false);
            return new AudioFormat(sampleRate, sampleSizeInBits, channels,
                    false, false);
        } else {
            LOG.warn("file is not a wav.");
            throw new IvcFileException();
        }
    }

}

测试通过,效果还不错。

相关标签: PCM MP3