AudioRecord与增益调整不工作的三星设备 [英] AudioRecord with Gain Adjustment not working on Samsung Device

查看:355
本文介绍了AudioRecord与增益调整不工作的三星设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了code使用记录音频文件 AudioRecord 键,而写在SD卡上的文件,我做两个版本。

I have written code for recording audio file using AudioRecord and while writing file on SD card i am making two version.

版本1 录音文件保存在SD卡上,因为它是。

Version 1 Recorded file is saved on SD Card as it is.

版本2 我申请增益功能上记录的文件并保存在SD卡上。

Version 2 I am applying Gain feature on recorded file and saving on SD card.

这适用于索尼埃里克松mobiles.Also音量真棒是提升在很大程度上。

This works awesome on Sony Ericson mobiles.Also audio volume is boost to great extent.

但我在努力使它在三星设备上工作。

But i am struggling to make it work on Samsung Devices.

当我玩录制的文件听起来像是会说话的汤姆:P

when i play recorded file it sound like Talking Tom :P

起初我还以为Samusung设备没有像我有用于创建组合 AudioRecorder

Initially i thought Samusung device did not like the combinations i have used to create AudioRecorder.

所以我用下面的方法,其中i循环到可用的配置和使用最佳配置来初始化AudioRecord。

So i used following approach in which i loop into available configuration and use best configuration to initialize AudioRecord.

public AudioRecord findAudioRecord() {
    for (int rate: mSampleRates) {
        for (short audioFormat: new short[] {
            AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT
        }) {
            for (short channelConfig: new short[] {
                AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO
            }) {
                try {
                    Log.i("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                    int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                    if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                        // check if we can instantiate and have a success
                        AudioRecord recorder = new AudioRecord(
                        AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                        if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    return null;
}

下面是code是做工不错索尼mobiles.But奋力在三星设备。

Below is Code that is working good on Sony mobiles.But Struggling to work on Samsung Devices.

public class EnvironmentRecorder extends Activity implements OnClickListener {

    private static final int RECORDER_BPP = 16;
    private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
    private static final String AUDIO_RECORDER_FOLDER = "MyRecorder";
    private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
    private static final int RECORDER_SAMPLERATE = 44100;
    private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
    private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
    private Button start, stop;
    private AudioRecord recorder = null;
    private int bufferSize = 0;
    private Thread recordingThread = null;
    private boolean isRecording = false;
    private static int[] mSampleRates = new int[] {
        8000, 11025, 22050, 44100
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        start = (Button) findViewById(R.id.start);
        stop = (Button) findViewById(R.id.stop);
        start.setOnClickListener(this);
        stop.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.start:
            startRecord();
            break;
        case R.id.stop:
            stopRecording();
            break;
        }
    }

    public EnvironmentRecorder() {

        try {
            bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private String getFilename1() {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File file = new File(filepath, AUDIO_RECORDER_FOLDER);

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

        return (file.getAbsolutePath() + "/" + "NotGained" + AUDIO_RECORDER_FILE_EXT_WAV);
    }

    private String getFilename2() {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File file = new File(filepath, AUDIO_RECORDER_FOLDER);

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

        return (file.getAbsolutePath() + "/" + "Gained" + AUDIO_RECORDER_FILE_EXT_WAV);
    }

    private String getTempFilename() {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        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 AudioRecord findAudioRecord() {
        for (int rate: mSampleRates) {
            for (short audioFormat: new short[] {
                AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT
            }) {
                for (short channelConfig: new short[] {
                    AudioFormat.CHANNEL_IN_MONO, AudioFormat.CHANNEL_IN_STEREO
                }) {
                    try {
                        Log.v("vipul", "Attempting rate " + rate + "Hz, bits: " + audioFormat + ", channel: " + channelConfig);
                        int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);

                        if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {
                            // check if we can instantiate and have a success
                            AudioRecord recorder = new AudioRecord(
                            AudioSource.DEFAULT, rate, channelConfig, audioFormat, bufferSize);

                            if (recorder.getState() == AudioRecord.STATE_INITIALIZED) return recorder;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    public void startRecord() {
        /*
         * recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
         * RECORDER_SAMPLERATE, RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING,
         * bufferSize);
         */

        recorder = findAudioRecord();

        recorder.startRecording();

        isRecording = true;

        recordingThread = new Thread(new Runnable() {

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

        recordingThread.start();
    }

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

        try {
            os = new FileOutputStream(filename);
        } catch (FileNotFoundException e) {
            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();
            }
        }
    }

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

            recorder.stop();
            recorder.release();

            recorder = null;
            recordingThread = null;
            copyWaveFile(getTempFilename(), getFilename1(), getFilename2());
            deleteTempFile();
        }

    }

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

        file.delete();
    }

    private void copyWaveFile(String inFilename, String outFileName1, String outFileName2) {
        FileInputStream in = null;
        FileOutputStream out1 = null, out2 = 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);
            out1 = new FileOutputStream(outFileName1);
            out2 = new FileOutputStream(outFileName2);
            totalAudioLen = in .getChannel().size();
            totalDataLen = totalAudioLen + 36;

            WriteWaveFileHeader(out1, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
            WriteWaveFileHeader(out2, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);

            while ( in .read(data) != -1) {

                out1.write(data); // Writing Non-Gained Data

                float rGain = 2.5f;
                for (int i = 0; i < data.length / 2; i++) {

                    short curSample = getShort(data[i * 2], data[i * 2 + 1]);
                    if (rGain != 1) {
                        // apply gain
                        curSample *= rGain;
                        // convert back from short sample that was "gained" to
                        // byte data
                        byte[] a = getByteFromShort(curSample);
                        // modify buffer to contain the gained sample
                        data[i * 2] = a[0];
                        data[i * 2 + 1] = a[1];
                    }

                }

                out2.write(data); // Writing Gained Data
            }
            out1.close();
            out2.close(); in .close();

            Toast.makeText(this, "Done!!", Toast.LENGTH_LONG).show();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private short getShort(byte argB1, byte argB2) {
        return (short)((argB1 & 0xff) | (argB2 << 8));

    }

    private byte[] getByteFromShort(short x) {
        // variant 1 - noise
        byte[] a = new byte[2];
        a[0] = (byte)(x & 0xff);
        a[1] = (byte)((x >> 8) & 0xff);

        // variant 2 - noise and almost broke my ears - very loud
        // ByteBuffer buffer = ByteBuffer.allocate(2);
        // buffer.putShort(x);
        // buffer.flip();

        return a;
    }

    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';
        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';
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        header[16] = 16;
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        header[20] = 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);
        header[33] = 0;
        header[34] = RECORDER_BPP;
        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);
    }

}

我想知道我是否需要添加任何额外的禄来让我AudioRecord舒适与三星设备。

I would like to know if i need to add any extra loc to make my AudioRecord comfortable with Samsung Devices.

推荐答案

我们也在努力与音频录制一些三星的Andr​​oid设备。不幸的是它似乎很破,因为相同的手机型号甚至不同版本的不同表现与同codeBase的。

We're also struggling with audio recording on some Samsung Android Devices. Unfortunately it seems to be very broken, as even different revisions of the same phone model are behaving differently with the same codebase.

下面是我目前的研究结果,希望你找到一些有用的东西:

Here are my current findings, hoping you find something useful:

1。残破的初始化:

不幸的是,您所使用的查询有效的录制配置的策略会失败,至少在三星Galaxy年轻王牌机型运行的是Android 2.3 问题是,一些无效AudioRecord配置,而不​​是简单地失败,将彻底砖音频采集子系统,如果尝试。你需要重新设置从这种状态中恢复了电话。

Unfortunately, the strategy you are using to query for valid recording configurations will fail at least on Samsung Galaxy Young and Ace models running Android 2.3 The problem is that some invalid AudioRecord configurations instead of simply failing, will completely brick the audio capture subsystem if tried. You'll need to reset the phone to recover from this state.

2。沿着相同的手机型号版本不一致的采样率支持

在一个旧银河王牌电话,录音@ 11025Hz,16位单声道会成功。在较新的王牌版本,这AudioRecord配置将被视为有效,但由此产生的记录会被扭曲,着有花栗鼠的效果。一个非常受欢迎的吉他调谐器的应用程序,具有硬codeD此采样率未能给这些手机$ P $的pcisely因为这个问题适当的调整读数!

On an older Galaxy Ace Phone, recording @ 11025Hz, 16-bit mono will succeed. On newer Ace revisions, this AudioRecord configuration will be accepted as valid, but the resulting recording will be distorted, with a "chipmunk" effect. A very popular guitar tuner app that has hardcoded this sampling rate is failing to give proper tuning readings on these phones precisely because of this problem!

3。极低的音量的音频采集上的一些配置。

在银河青年和Galaxy王牌,从麦克风或默认的音频源@ 44,100Hz(据推测是典型的速度在那里一切都应该正常工作)记录产生失真的,但非常小批量的记录。我还没有找到一种方法来解决比软件扩增这另一个(它是放大一个非常低分辨率图像的等效,结果的consecuentjageddnes)。

In Galaxy Young and Galaxy Ace, recording from the mic or default audio source @ 44,100Hz (the supposedly canonical rate where everything should work fine) produces an undistorted, but extremely low-volume recording. I haven't found yet a way to fix this other than software amplification (which is the equivalent of magnifying a very low res image, with the consecuent "jageddnes" of the result).

4。如果不支持所有的音频采集源上的典型44,100Hz采样率。

在银河青年和Galaxy王牌,从摄像机源录制失败@ 44,100Hz。 (同样,该配置将被视为有效)生产完全是垃圾。然而,记录@ 8,000Hz,16,000Hz和48,000Hz工作正常,并产生一个记录具有非常可接受的音量。什么是令人沮丧的是,根据Android的文档,44,100Hz的采样率所有设备都应该支持。

In Galaxy Young and Galaxy Ace, recording from the Camcorder source fails @ 44,100Hz. (again, the configuration will be accepted as valid) producing complete garbage. However, recording @ 8,000Hz, 16,000Hz and 48,000Hz works fine and produces a recording with very acceptable volume levels. What is frustrating is that according to the Android documentation, 44,100Hz is a sampling rate all devices SHOULD support.

5。 OpenSL不修复任何报告的问题。

与NDK和OpenSL工作产生相同的描述的结果。看来,AudioRecorder类只是包装调用OpenSL,问题要么是基于硬件的,或埋在内核code较低级别的梯队。

Working with the NDK and OpenSL produces the same described results. It seems that the AudioRecorder class is simply wrapping calls to OpenSL, and the problem is either hardware based, or buried at a lower-level tier in the kernel code.

这种情况是非常可惜的是真的,因为这些车型正变得非常流行的 - 至少在墨西哥

This situation is very unfortunately indeed, as these models are becoming very popular - at least in Mexico.

祝你好运 - 并请报告,如果你有更好的运气,这些手机的工作。 =)

Good luck - and please report if you had better luck working with these phones. =)

这篇关于AudioRecord与增益调整不工作的三星设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆