Как конвертировать audio raw в flac в Android



I запись звука с помощью класса audoiRecord. Теперь я хочу конвертировать аудио raw файл в формат * flac. Я конвертирую * raw файл в wav следующим образом:



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();
}
}


Этот фрагмент кода отвечает за заголовок файла



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);
}


Я не понимаю, какими должны быть параметры файла * flac

640   2  

2 ответов:

Для преобразования данных pcm в формат flac требуется кодер. Вы не можете просто изменить заголовок и ожидать, что содержимое будет работать как flac.

Android (по крайней мере до версии 4.1) не включает кодер FLAC, хотя есть декодер, поддерживаемый начиная с версии 3.1 (Источник: http://developer.android.com/guide/appendix/media-formats.html).

у меня нет прямого опыта, но я видел, как люди используют ffmpeg в качестве кодера flac. Это проект audioboo-android, который содержит стандартные устройства хранения информации/устройства хранения информации++ шифратор, выглядит интересно.

Вот чистый кодер java FLAC: http://javaflacencoder.sourceforge.net

Некоторые классы используют API javax, но их можно безопасно удалить, не затрагивая основные классы кодировщика.

Вот пример кода. Объект record имеет тип 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;
}

Для преобразования коротких данных в данные int:

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;
}

Comments

    Ничего не найдено.