Странная проблема в объединении аудиофайлов и воспроизведении в разных версиях API

Все, я использую Media Recorder для записи аудио.

Случай 1: Если я использую Android версии 2.2, установленные устройства, мой записанный звук комбинируется и хорошо работает.

Случай 2: если я использую его в Android 1.6 установленных устройствах, я не могу воспроизвести объединенный аудиофайл.

В нем воспроизводится только самый первый записанный звук, а следующие записанные аудиофайлы не содержат звука.

Также я не получаю любую ошибку в Logcat.

Я использовал следующий код для записи звука:

    mRecorder = new MediaRecorder();
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
    mRecorder.setOutputFile(main_record_file);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mRecorder.prepare();
    mRecorder.start();

Также я пробовал для mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

Код для объединения аудиофайла:

    public void createCombineRecFile(){
    combined_file_stored_path=getFilename_combined_raw(); // File path in String to store recorded audio
    byte fileContent[]=null;
    FileInputStream ins;
    FileOutputStream fos = null;
    try{
        fos = new FileOutputStream(combined_file_stored_path,true);
    }
    catch (FileNotFoundException e1){
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    for(int i=0;i<audNames.size();i++){
        try{
            File f=new File(audNames.get(i));
            Log.v("Record Message", "File Length=========>>>"+f.length());
            fileContent = new byte[(int)f.length()];
            ins=new FileInputStream(audNames.get(i));
            int r=ins.read(fileContent);// Reads the file content as byte from the list.
            Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
            fos.write(fileContent);//Write the byte into the combine file.

            Log.v("Record Message", "File======="+i+"is Appended");

        }
        catch (FileNotFoundException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try{
        fos.close();
        Log.v("Record Message", "===== Combine File Closed =====");
    }
    catch (IOException e){
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Позвольте мне знать любые детали. Спасибо.

Ответ 1

Каждый аудиофайл имеет свой собственный заголовок (включает информацию о длине/выборках и т.д.) - путем объединения файлов так, как вы делаете полученный файл, имеет несколько заголовков, по одному на исходный файл (в зависимости от точного формата с смещениями файлов и т.д..). Таким образом, полученный файл НЕ правильный с точки зрения спецификации формата файла.

Новая версия Android более разрешительна и работает/работает с "несколькими заголовками"... старые версии не...

Чтобы создать правильно объединенный аудиофайл, вы должны соответствовать спецификации, которая среди прочего означает создание одного нового заголовка, который описывает все включенные аудио...

Используйте для комбинации аудиофайлов другой подход - например, через ffmpeg (см. этот для того, как сделать ffmpeg для android).

Ответ 2

Предисловие: не проверял это, но я не понимаю, почему он не должен работать.

Если заголовки являются причиной этой проблемы, вы можете решить ее очень легко. Используя код, который вы указали, кодировка AMR-NB. Согласно этот документ, заголовок AMR - это просто первые 6 байтов, которые являются 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A. Если заголовки в последующих файлах вызывают проблему, просто опустите эти байты из последующих файлов, например.

write all bytes of first file
write from byte[6] -> byte[end] of subsequent files

Сообщите мне, как это происходит.

EDIT: по запросу измените блок try на:

try{
        File f=new File(audNames.get(i));
        Log.v("Record Message", "File Length=========>>>"+f.length());
        fileContent = new byte[(int)f.length()];

        ///////////////new bit////////

        //same as you had, this opens a byte stream to the file
        ins=new FileInputStream(audNames.get(i));
        //reads fileContent.length bytes
        ins.read(fileContent);
        //now fileContent contains the entire audio file - in bytes.
        if(i>0){
            //we are not writing the first audio recording, but subsequent ones
            //so we don't want the header included in the write

            //copy the entire file, but not the first 6 bytes
            byte[] headerlessFileContent = new byte[fileContent.length()-6];
            for(int j=6; j<fileContent.length();j++){
                headerlessFileContent[j-6] = fileContent[j];
            }
            fileContent = headerlessFileContent;
        }
        ////////////////////////////

        Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
        fos.write(fileContent);//Write the byte into the combine file.

        Log.v("Record Message", "File======="+i+"is Appended");

    }