Как конвертировать 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
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имеет типAudioRecordtry { // 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