【问题标题】:Implementing a high pass audio filter in android在android中实现高通音频过滤器
【发布时间】:2016-02-20 07:59:23
【问题描述】:

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

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

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 的浮动缓冲区设置为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 中的字节数组上使用的不同高通滤波器提出建议。

更新:我想通了。这是我将字节转换为浮点数的更新函数:

 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;
}

【问题讨论】:

    标签: android arrays audio type-conversion audio-recording


    【解决方案1】:

    两个字节样本是否代表浮点值?它们可以在 -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;
    

    【讨论】:

    • 我不确定,我通过从 audioRecord 中读取来获取字节。我在我原来的问题中添加了代码。我尝试了你的建议,但不幸的是它没有用。
    【解决方案2】:

    您需要将字节对转换为带符号的短整数,然后将其缩放为 -1.0 到 1.0 范围内的浮点数。

    根据数据的字节顺序,以下行之一将转换为有符号的 16 位。

    short shortSample = (short)(bytes[i]) | (short)(bytes[i+1]) << 8);
    short shortSample = (short)(bytes[i] << 8) | (short)(bytes[i+1]));
    

    然后缩放到浮动:

    float sample = shortSample / 32768f;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-02
      • 2016-03-23
      • 1970-01-01
      • 2022-07-26
      • 1970-01-01
      • 2014-03-13
      • 2011-05-05
      • 2023-03-21
      相关资源
      最近更新 更多