Wav-файл, записанный с помощью AudioRecord, звучит ускоренно и пропускает кадры при воспроизведении

Я использую AudioRecord для чтения данных микрофона и RandomAccessFile для записи их в файл wav. Это код:

public class MainActivity extends Activity {
    AudioManager am = null;
    AudioRecord record =null;
    // AudioTrack track =null;
    final int SAMPLE_FREQUENCY = 44100;
    final int SIZE_OF_RECORD_ARRAY = 1024;  // 1024 ORIGINAL
    final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
    int i= 0;
    boolean isPlaying = false;
    private volatile boolean keepThreadRunning;
//  private RandomAccessFile stateFile, stateFileTemp, savToDisk;
    private RandomAccessFile savToDisk;
    private FileDescriptor fd = new FileDescriptor(); 
    private File delFile, renFile;
    String stateFileLoc = Environment.getExternalStorageDirectory().getPath(); 
    // To keep hederWriter() happy
    private short nChannels = 1;
    private int sRate = SAMPLE_FREQUENCY;
    private short mBitsPersample = 16; // represents 16 bits of one PCM sample
    private int payload;

    class MyThread extends Thread{
        private volatile boolean needsToPassThrough;
        // /*
        MyThread(){
            super();
        }

        MyThread(boolean newPTV){
            this.needsToPassThrough = newPTV;
        }
        // */

        // /*
        @Override
        public void run(){
             short[] lin = new short[SIZE_OF_RECORD_ARRAY];
            // byte[] lin = new byte[SIZE_OF_RECORD_ARRAY];
            int num = 0;
            // /*
            if(needsToPassThrough){
                record.startRecording();
                // track.play();
            }
            // */
            while (keepThreadRunning) {
            // while (!isInterrupted()) {
                // num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
                num = record.read(lin, 0, lin.length);
                try {
                    // savToDisk.write(lin); // use only this line if lin is a byte array

                    // use the for loop block below if lin is an array of short
                    for(i=0;i <lin.length; i++)
                        savToDisk.writeShort(Short.reverseBytes(lin[i]));

                    // payload += lin.length; // use this line if lin is an array of byte
                    payload = payload + (lin.length)*2;
                    fd.sync();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                /*
                catch (SyncFailedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                */
            }
            // /*
            record.stop();
            // track.stop();
            record.release();
            // track.release();
            // */
        }
        // */

        // /*
        public void stopThread(){
            keepThreadRunning = false;
        }
        // */
    }

    MyThread newThread;

    private void init() {
        int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        // Toast.makeText(getApplicationContext(), Integer.toString(min), Toast.LENGTH_SHORT).show(); // Shows 4096
        record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
                                 AudioFormat.ENCODING_PCM_16BIT, min);
        // int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        // track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
        am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        am.setMode(AudioManager.MODE_IN_COMMUNICATION);

        try {
            savToDisk = new RandomAccessFile(stateFileLoc+"/audSampData.wav", "rw");

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            fd = savToDisk.getFD();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 

    }

    private void writeHeader(){
        try {
            savToDisk.setLength(0); // Set file length to 0, to prevent unexpected behavior in case the file already existed
            savToDisk.writeBytes("RIFF");
            savToDisk.writeInt(0); // Final file size not known yet, write 0 
            savToDisk.writeBytes("WAVE");
            savToDisk.writeBytes("fmt ");
            savToDisk.writeInt(Integer.reverseBytes(16)); // Sub-chunk size, 16 for PCM
            savToDisk.writeShort(Short.reverseBytes((short) 1)); // AudioFormat, 1 for PCM
            savToDisk.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo
            savToDisk.writeInt(Integer.reverseBytes(sRate)); // Sample rate
            savToDisk.writeInt(Integer.reverseBytes(sRate*nChannels*mBitsPersample/8)); // Byte rate, SampleRate*NumberOfChannels*mBitsPersample/8
            savToDisk.writeShort(Short.reverseBytes((short)(nChannels*mBitsPersample/8))); // Block align, NumberOfChannels*mBitsPersample/8
            savToDisk.writeShort(Short.reverseBytes(mBitsPersample)); // Bits per sample
            savToDisk.writeBytes("data");
            savToDisk.writeInt(0); // Data chunk size not known yet, write 0
            fd.sync();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    protected void onResume(){
        super.onResume();
        // newThread.stopThread();
        Log.d("MYLOG", "onResume() called");
        init();
        writeHeader();
        keepThreadRunning = true;
        // */


        // newThread = new MyThread(true);
        newThread = new MyThread(isPlaying);
        newThread.start();

    }

    @Override
    protected void onPause(){
        super.onPause();
        Log.d("MYLOG", "onPause() called");
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
        try {
            savToDisk.seek(4);
            savToDisk.writeInt(Integer.reverseBytes(36+payload));
            savToDisk.seek(40);
            savToDisk.writeInt(Integer.reverseBytes(payload));
            savToDisk.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
        payload = 0;
        Log.d("MYLOG","onCreate() called");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
        // killProcess(android.os.Process.myPid());
        // newThread.interrupt();
        // delFile.delete();
         Log.d("MYLOG", "onDestroy() called");
         /*
         try {
            savToDisk.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        */
    }

    public void passStop(View view){
        Button playBtn = (Button) findViewById(R.id.button1);  
        // /*
        if(!isPlaying){
            record.startRecording();
            // track.play();
            isPlaying = true;
            playBtn.setText("Pause");
        }
        else{
           record.stop();
           // track.pause();
           isPlaying=false;
           playBtn.setText("Pass through");
        }
        // */
    }



}  

Когда я проигрываю wav-файл в аудиоплеере, он звучит ускоренно, а также, кажется, пропускает кадры. Каковы могут быть причины этого? Я считаю, что проблема с пропуском кадров, вероятно, связана с тем, что я использовал функцию writeShort() для записи каждого элемента короткого массива, в котором хранятся данные аудиосэмпла отдельно, но если это так, пожалуйста, предложите обходной путь, который включает в себя запись данные в виде шорт (и не используя функцию write(byte[]), потому что мне нужно использовать части этого кода в моем основном проекте, который включает в себя получение аудиосэмплов в коротком массиве). И еще, почему он ускоряется?


person user13267    schedule 26.08.2013    source источник


Ответы (1)


Взгляните на это, этот вопрос поставил меня на правильный путь.

Android: запись звука с использованием воспроизведения класса audiorecord как ускоренная перемотка

person Dwebtron    schedule 12.03.2014