android - 在android中实现高通音频滤波器

标签 android arrays audio type-conversion audio-recording

我正在尝试对从 audioRecord 获得的麦克风数据实现高通音频滤波器。

我从麦克风获得的数据是一个 16 位 PCM 音频字节数组。我试图使用 TarsosDSP它提供了用于高通滤波的API。但是,作为输入,它需要一个 float 组,因此我将字节转换为 float 组并运行高通滤波器。为了确认结果,我将过滤后的数据保存在波形文件中,但听起来完全失真。

public static byte[] highPassFilter( byte[] buffer, WaveHeader waveHeader, float frequency) {

    HighPass highPass = new HighPass(frequency, waveHeader.getSampleRate());

    TarsosDSPAudioFormat format = new TarsosDSPAudioFormat(waveHeader.getSampleRate(),waveHeader.getBitsPerSample(),waveHeader.getChannels(),true, false);
    AudioEvent audioEvent = new AudioEvent(format);
    float[] f_buffer = bytesToFloats(buffer);
    audioEvent.setFloatBuffer(f_buffer);

    highPass.process(audioEvent);
    buffer = audioEvent.getByteBuffer();

    byte[] data = PCMtoWav(buffer, waveHeader.getSampleRate(),     waveHeader.getChannels(), waveHeader.getBitsPerSample());
    writeWavFile(data);

    return buffer;
}

public static float[] bytesToFloats(byte[] bytes) {
    float[] floats = new float[bytes.length / 2];
    for(int i=0; i < bytes.length; i+=2) {
        floats[i/2] = bytes[i] | (bytes[i+1] < 128 ? (bytes[i+1] << 8) : ((bytes[i+1] - 256) << 8));
    }
    return floats;
}

waveHeader中的数据是: Sample rate = 11025 getBitsPerSample = 16 getChannels = 1

我最好的猜测是 bytesToFloats 转换是错误的。为了验证这一点,我只是设置 audioEvent 的 float 缓冲区与 audioEvent.setFloatBuffer然后用 audioEvent.getByteBuffer 检索它这也导致音频文件完全失真。

从audioRecord中读取字节缓冲区:

audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 220500);
....
buffer = new byte[frameByteSize];
byte[] audioRecord.read(buffer, 0, frameByteSize);

任何人都知道如何解决这个问题,或者对我可以在 android 中的字节数组上使用的不同高通滤波器提出建议。

更新:我明白了。这是我更新的从字节转换为 float 的函数:

 public static float[] bytesToFloats(byte[] bytes) {
    float[] floats = new float[bytes.length / 2];
    short[] shorts = new short[bytes.length/2];
    ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
    for(int i=0; i < bytes.length; i+=2) {
        floats[i/2] = shorts[i/2] / 32768f;
    }
    return floats;
}

最佳答案

这两个字节样本是否代表浮点值?它们可以在 -32,768 到 32,767 的范围内做空。此外,对于样本的浮点表示,-1.0 到 1.0 范围内的值很常见。

我会尝试:

short sample = bytes[i] | (bytes[i+1] < 128 ? (bytes[i+1] << 8) : ((bytes[i+1] - 256) << 8));
floats[i/2] = (float)sample / 32,768f;

关于android - 在android中实现高通音频滤波器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33782501/

相关文章:

javascript - 以HTML5音频显示总计时

java - Android:重写主 Activity 的 onCreate 方法

php - 如何使用 in_array 函数比较两个数组

javascript - 旨在返回数组的函数返回未定义。函数内的 Console.log(array) 返回数组

arrays - 确定两个数组在排列方面是否相同?

javascript - 如何在React中使用audioWorklet.addModule?

android - 在 fragment onCreateView 或 onCreate 方法中哪个是初始化 ViewModel 的最佳位置?

java - 卸载并再次安装应用程序时,Firebase 身份验证返回特定用户

java - 检测来自另一部手机的输入?

html - 在https://modernizr.com/download上找不到Modernizr.load()或HTML5音频