How convert audio raw to flac in Android

2019-06-27 23:08发布

I recording audio with class audoiRecord. Now I want convert audio raw file to *flac format. I convert *raw file to wav next way:

private void copyWaveFile(String inFilename,String outFilename){
    FileInputStream in = null;
    FileOutputStream out = null;
    long totalAudioLen = 0;
    long totalDataLen = totalAudioLen + 36;
    long longSampleRate = sampleRate;
    int channels = 2;
    long byteRate = RECORDER_BPP * sampleRate * channels/8;
    byte[] data_pcm = new byte[mAudioBufferSize];
    try {
        in = new FileInputStream(inFilename);
        out = new FileOutputStream(outFilename);
        totalAudioLen = in.getChannel().size();
        totalDataLen = totalAudioLen + 36;
        Log.i(TAG,"File size: " + totalDataLen);
        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
        longSampleRate, channels, byteRate);
        while(in.read(data_pcm) != -1){
            out.write(data_pcm);
        }
        in.close();
        out.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This piece of code is responsible for the file header

private void WriteWaveFileHeader(
                 FileOutputStream out, long totalAudioLen,
                 long totalDataLen, long longSampleRate, int channels,
                 long byteRate) throws IOException {

     byte[] header = new byte[44];

     header[0] = 'R';  // RIFF/WAVE header
     header[1] = 'I';
     header[2] = 'F';
     header[3] = 'F';
     header[4] = (byte) (totalDataLen & 0xff);
     header[5] = (byte) ((totalDataLen >> 8) & 0xff);
     header[6] = (byte) ((totalDataLen >> 16) & 0xff);
     header[7] = (byte) ((totalDataLen >> 24) & 0xff);
     header[8] = 'W';
     header[9] = 'A';
     header[10] = 'V';
     header[11] = 'E';
     header[12] = 'f';  // 'fmt ' chunk
     header[13] = 'm';
     header[14] = 't';
     header[15] = ' ';
     header[16] = 16;  // 4 bytes: size of 'fmt ' chunk
     header[17] = 0;
     header[18] = 0;
     header[19] = 0;
     header[20] = 1;  // format = 1
     header[21] = 0;
     header[22] = (byte) channels;
     header[23] = 0;
     header[24] = (byte) (longSampleRate & 0xff);
     header[25] = (byte) ((longSampleRate >> 8) & 0xff);
     header[26] = (byte) ((longSampleRate >> 16) & 0xff);
     header[27] = (byte) ((longSampleRate >> 24) & 0xff);
     header[28] = (byte) (byteRate & 0xff);
     header[29] = (byte) ((byteRate >> 8) & 0xff);
     header[30] = (byte) ((byteRate >> 16) & 0xff);
     header[31] = (byte) ((byteRate >> 24) & 0xff);
     header[32] = (byte) (2 * 16 / 8);  // block align
     header[33] = 0;
     header[34] = RECORDER_BPP;  // bits per sample
     header[35] = 0;
     header[36] = 'd';
     header[37] = 'a';
     header[38] = 't';
     header[39] = 'a';
     header[40] = (byte) (totalAudioLen & 0xff);
     header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
     header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
     header[43] = (byte) ((totalAudioLen >> 24) & 0xff);

     out.write(header, 0, 44);
}

I do not understand what should be the parameters of the *flac file

2条回答
爷、活的狠高调
2楼-- · 2019-06-27 23:27

Here's a pure java FLAC encoder: http://javaflacencoder.sourceforge.net

Some of the classes use the javax apis, but they can be safely deleted without affecting the main encoder classes.

Here's some sample code. The record object is of type AudioRecord

try {
                    // Path to write files to
                    String path = Environment.getExternalStoragePublicDirectory("/test").getAbsolutePath();

                    String fileName = name+".flac";
                    String externalStorage = path;
                    File file = new File(externalStorage + File.separator + fileName);

                    // if file doesnt exists, then create it
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    short sData[] = new short[BufferElements2Rec];

                    FileOutputStream os = null;
                    try {
                        os = new FileOutputStream(file);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }


                    FLACEncoder flacEncoder = new FLACEncoder();
                    StreamConfiguration streamConfiguration = new StreamConfiguration(1,StreamConfiguration.MIN_BLOCK_SIZE,StreamConfiguration.MAX_BLOCK_SIZE,44100,16);

                    FLACFileOutputStream flacOut = new FLACFileOutputStream(os);
                    flacEncoder.setStreamConfiguration(streamConfiguration);
                    flacEncoder.setOutputStream(flacOut);
                    flacEncoder.openFLACStream();


                    record.startRecording();

                    int totalSamples = 0;

                    while (isRecording) {
                        record.read(sData, 0, BufferElements2Rec);
                        totalSamples+=BufferElements2Rec;

                        flacEncoder.addSamples(short2int(sData),BufferElements2Rec);

                        flacEncoder.encodeSamples(BufferElements2Rec, false);
                    }

                    int available = flacEncoder.samplesAvailableToEncode();
                    while(flacEncoder.encodeSamples(available,true) < available) {
                        available = flacEncoder.samplesAvailableToEncode();
                    }
                    try {
                        flacOut.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    record.stop();
                } catch(IOException ex) {
                    ex.printStackTrace();

                }

                record.release();
                record = null;
}

For converting the short data into int data:

private int[] short2int(short[] sData) {
    int length = sData.length;
    int[] iData = new int[length];
    for(int i=0;i<length;i++) {
        iData[i] = sData[i];
    }
    return iData;
}
查看更多
该账号已被封号
3楼-- · 2019-06-27 23:30

You need an encoder to convert pcm data to flac format. You cannot just change the header and expect the content to work as flac.

Android (at least till 4.1) does not include a FLAC encoder, although there is a decoder supported from 3.1 onwards (Source: http://developer.android.com/guide/appendix/media-formats.html).

I do not have direct experience, but have seen people use ffmpeg as a flac encoder. This project audioboo-android, which contains the native libFLAC/libFLAC++ encoder, looks interesting.

查看更多
登录 后发表回答