prafull agrawal Ответов: 2

Ошибка аудиорегистратора Androide (Wav Recorder)


Я работаю над android-приложением, в котором хочу записать голос пользователя в формате wav и выполнить его обработку. Я хочу частоту дискретизации 22050 Гц и 16-битный подписанный формат с моноканалом. Я получил некоторый код, выполнив поиск в google, и интегрировал его в свое приложение, но когда я запускаю свое приложение, оно дает мне 3 ошибки:

E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioRecord-JNI: Error creating AudioRecord instance: initialization check failed with status -1.
E/android.media.AudioRecord: Error code -20 when initializing native AudioRecord object.


Я добавил разрешение в манифест, но ошибка сохраняется.

1. Wavrecordnew.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.TimerTask;
import java.util.Timer;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.View;
import android.widget.Button;

public class Wavrecordernew {
    private static final int RECORDER_BPP = 16;
    private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
    private static final String AUDIO_RECORDER_FOLDER = "Automator";
    private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
    private static final int RECORDER_SAMPLERATE = 22050;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private static AudioRecord recorder = null;
    private static int bufferSize = 0;
    //bufferSize *= 2;
    private static Thread recordingThread = null;
    private static boolean isRecording = false;
    private static String filenme,wavpath;

   // bufferSize = AudioRecord.getMinBufferSize(8000,AudioFormat.CHANNEL_CONFIGURATION_MONO,AudioFormat.ENCODING_PCM_16BIT);


    private static String getFilename(){
        String filepath = wavpath;
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);

        if(!file.exists()){
            file.mkdirs();
        }

        return (file.getAbsolutePath() + "/" + filenme);
    }

    private static String getTempFilename(){
        String filepath = wavpath;
        File file = new File(filepath,AUDIO_RECORDER_FOLDER);

        if(!file.exists()){
            file.mkdirs();
        }

        File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);

        if(tempFile.exists())
            tempFile.delete();

        return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
    }

    public static void startRecording(String filepathfrmdis, String filenamefrmdis){

        bufferSize = (AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_IN_MONO,AudioFormat.ENCODING_PCM_16BIT))*200;
        filenme = filenamefrmdis;
        wavpath = filepathfrmdis;
        recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);

        int i = recorder.getState();
        if(i==1)
            recorder.startRecording();

        isRecording = true;

        recordingThread = new Thread(new Runnable() {

            @Override
            public void run() {
                writeAudioDataToFile();
            }
        },"AudioRecorder Thread");

        recordingThread.start();

        new java.util.Timer().schedule(
                new java.util.TimerTask() {
                    @Override
                    public void run() {
                       stopRecording();
                    }
                },
                9000
        );

    }

    private static void writeAudioDataToFile(){
        byte data[] = new byte[bufferSize];
        String filename = getTempFilename();
        FileOutputStream os = null;

        try {
            os = new FileOutputStream(filename);
        } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
            e.printStackTrace();
        }

        int read = 0;

        if(null != os){
            while(isRecording){
                read = recorder.read(data, 0, bufferSize);

                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                    try {
                        os.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void stopRecording(){
        if(null != recorder){
            isRecording = false;

            int i = recorder.getState();
            if(i==1)
                recorder.stop();
            recorder.release();

            recorder = null;
            recordingThread = null;
        }

        copyWaveFile(getTempFilename(),getFilename());
        deleteTempFile();
    }


    private static void deleteTempFile() {
        File file = new File(getTempFilename());

        file.delete();
    }

    private static void copyWaveFile(String inFilename,String outFilename){
        FileInputStream in = null;
        FileOutputStream out = null;
        long totalAudioLen = 0;
        long totalDataLen = totalAudioLen + 36;
        long longSampleRate = RECORDER_SAMPLERATE;
        int channels = 2;
        long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;

        byte[] data = new byte[bufferSize];

        try {
            in = new FileInputStream(inFilename);
            out = new FileOutputStream(outFilename);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;

            //AppLog.logString("File size: " + totalDataLen);

            WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                    longSampleRate, channels, byteRate);

            while(in.read(data) != -1){
                out.write(data);
            }

            in.close();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

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

}


2. DisplayRecordingMessageActivity.java (вызов волнового регистратора)

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.io.File;

public class DisplayRecordingMessageActivity extends AppCompatActivity {
    public final static String EXTRA_MESSAGE_USER_NAME = "com.mycompany.myfirstapp.MESSAGE";
    private static Wavrecordernew mRecorder;
    //private static Wavrecordernew mRecordernew;
    private static int filenum = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display_recording_message);

        Intent intentrecordingtranfred = getIntent();
        String message = intentrecordingtranfred.getStringExtra(MyActivity.EXTRA_MESSAGE_RECORDING);
        TextView textView = (TextView) findViewById(R.id.recorderintructionstxtView);
        textView.setText(message);
        textView.setTextSize(16);

    }

    /** Called when the user clicks the Save button */
    public void saveusername(View view) {

        EditText editUsername = (EditText) findViewById(R.id.edit_username);
        String username = editUsername.getText().toString();

        if (!("").equals(username)) {

            String filename = username + filenum + ".wav";
            String wavfilepath = this.getFilesDir().getPath();

            mRecorder.startRecording(wavfilepath,filename);

        }
        else
        {
            //popup saying please enter username and press save
            AlertDialog.Builder builder1 = new AlertDialog.Builder(DisplayRecordingMessageActivity.this);
            builder1.setTitle("Invalid");
            builder1.setMessage("Please Enter your name and then press save");
            builder1.setCancelable(false);
            //builder1.setIcon(R.drawable.delete);
            builder1.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });

            AlertDialog alert11 = builder1.create();
            alert11.show();
        }
    }

}


3. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="in.automator.automator">

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="15" />

    <application

        android:allowBackup="true"

        android:icon="@mipmap/ic_launcher"

        android:label="@string/app_name"

        android:supportsRtl="true"

        android:theme="@style/AppTheme">
        <activity

            android:name=".MyActivity"

            android:label="@string/app_name"

            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity

            android:name=".DisplayRecordingMessageActivity"

            android:label="@string/title_activity_display_recording_message"

            android:parentActivityName=".MyActivity"

            android:theme="@style/AppTheme.NoActionBar">
            <meta-data

                android:name="android.support.PARENT_ACTIVITY"

                android:value="in.automator.automator.MyActivity" />

        </activity>
    </application>
    <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>

</manifest>


Я ищу решения с последних 5 дней.

Заранее спасибо.

Richard MacCutchan

Что означают эти коды ошибок?

prafull agrawal

Если бы я знал, зачем бы я спрашивал здесь?

Richard MacCutchan

Как ты думаешь, кто-нибудь здесь поймет, что они означают? Мы понятия не имеем, откуда взялся этот код, который вы нашли в интернете, или кто его написал.

prafull agrawal

Привет эти ошибки касаются класса AudioRecorder самого android, и я разместил весь код здесь для справки кодеров, если вы не знаете android, то, пожалуйста, не смотрите в него. Благодарим

Richard MacCutchan

Если вам нужна помощь в решении этой проблемы, пожалуйста, предоставьте полную информацию, а не сбрасывайте весь свой код и ожидайте, что другие люди сделают отладку.

prafull agrawal

Я опубликовал только свой полный код и код wav recorder, который я использовал в своем коде,
Я забыл упомянуть справочную ссылку для кода записи wav http://www.edumobile.org/android/audio-recording-in-wav-format-in-android-programming/

2 Ответов

Рейтинг:
2

ridoy

Я бы предложил вам здесь 2 вещи:

1. Использование

<uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
до тега </application>, а не после него.

2. вы запускали это один раз и не вызывали recordInstance.release()? Если это так, то вы, возможно, связали аудиоресурсы, и он, скорее всего, не будет работать, пока вы не перезагрузите телефон.


prafull agrawal

Спасибо за ответ, я попытался использовать Шаг 1, но он дал мне следующие ошибки, и код не запускался ни разу, так что никаких проблем с привязкой ресурсов не возникло.

E/AudioRecord: не удалось получить аудиовход для источника записи 1, частота дискретизации 22050, формат 0x1, маска канала 0x10, сеанс 40, флаги 0
Е/осуществление аудиозаписи-средой JNI: создание экземпляра осуществление аудиозаписи ошибка: проверить инициализацию с состоянием -22.
Е/андроид.СМИ.AudioRecord: код ошибки -20 при инициализации собственного объекта AudioRecord.

ridoy

Тогда возможным решением был бы пункт 2 моего ответа. Там может быть немного других вещей, вы можете следовать этим и исследовать свои: http://stackoverflow.com/questions/4843739/audiorecord-object-not-initializing, http://stackoverflow.com/questions/8972858/errors-when-recording-sound-in-android, http://stackoverflow.com/questions/4807428/audiorecord-could-not-get-audio-input-for-record-source-1

prafull agrawal

Поскольку recordInstance не инициализируется до того, как я использую его в первый раз, и это дает мне ту же ошибку. Поэтому я думаю, что пункт 2 не будет иметь места. Спасибо.

prafull agrawal

Мне удалось устранить вышеуказанную ошибку, т. е. E/AudioRecord: не удалось получить аудиовход для источника записи 1, частота дискретизации 22050, формат 0x1, маска канала 0x10, сеанс 40, флаги 0
Е/осуществление аудиозаписи-средой JNI: создание экземпляра осуществление аудиозаписи ошибка: проверить инициализацию с состоянием -22.
Е/андроид.СМИ.AudioRecord: код ошибки -20 при инициализации собственного объекта AudioRecord.

Но старый вернулся, я имею в виду, что ошибки, о которых я упоминал в этом вопросе, вернулись. Не повезло.

Рейтинг:
1

Member 13989987

Вы должны использовать этот метод для вашей проблемы.


@RequiresApi(api = Build.VERSION_CODES.M)
public void getPermissionToRecordAudio() {
    // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid
    // checking the build version since Context.checkSelfPermission(...)
    // 2) Always check for permission (even if permission has already been granted)
    // since the user can revoke permissions at any time through Settings
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {

        // The permission is NOT already granted.
        // Check if the user has been asked about this permission already and denied
        // it. If so, we want to give more explanation about why the permission is needed.
        // Fire off an async request to actually get the permission
        // This will show the standard permission request dialog UI
        requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                RECORD_AUDIO_REQUEST_CODE);

    }
}