python 音频读取 wave与librosa的区别

记录一下在python音频读取以及进行FFT变换时遇到的问题。在进行音频读取并进行FFT变换时发现一个奇怪的问题,我有一个音频1000HZ.wav,用wave和librosa.load读取得到的频率结果不一样。

import librosa
import numpy as np
import wave
import pyaudio
import matplotlib.pyplot as plt
import librosa.display

def librosa_fft(filename):
    #读取声音文件
    x, sr = librosa.load(filename, sr=None)
    print(sr)
    num = 1
    remainder = x.shape[0] % num
    s = slice(remainder, x.shape[0])
    x = x[s]
    print(x.shape[0])

    Fs = sr #采样频率
    T = 1/Fs #采样周期,只相邻两数据点的时间间隔
    freq_list = []
    brand_length = int(x.shape[0] / num)
    print('brand_length:%s' % brand_length)
    #将数据分割成N份
    for i in range(0, num):
        brand_s = slice(i * brand_length, (i + 1) * brand_length)
        brand_data = x[brand_s]
        #对数据做快速傅里叶变换
        ffts = np.fft.fft(brand_data)
        #取绝对值
        pows = np.abs(ffts)
        #归一化处理
        pows = pows * 2 / brand_length
        #取得频率范围
        freqs = np.fft.fftfreq(brand_length, T)
        # 频率为0的重复累积了两次,需要减半处理
        pows[freqs == 0] = pows[freqs == 0] / 2  # 频率为0的重复累积了两次,需要减半处理
        #pows = pows[freqs >= 0]  # 取出对应的正频率的幅值
        # 取出对应的正频率的幅值
        freqs = freqs[freqs >= 0]

        # 常规显示采样频率一半的频谱
        d = int(len(pows) / 2)
        #print(d)
        # 仅显示频率在6000以下的频谱
        while freqs[d-1] > 6000:
            d -= 10
        #print(d)

        #取实数
        pows_real = [n.real for n in pows[:d - 1]]
        max_pow = max(pows_real)
        id = pows_real.index(max_pow)  # 最大值索引
        freq_list.append(freqs[id])

        plt.plot(freqs[:d - 1], pows_real[:d - 1], 'r')
        plt.show()

        #plt.plot(freqs[freqs >= 0], pows[freqs >= 0])
        #plt.show()
    print(freq_list)
    average = np.mean(freq_list)
    result_list = [n >= average for n in freq_list]
    return result_list

def load_file(file_path, oraginal=True):
    # 只读方式打开WAV文件
    wf = wave.open(file_path, 'rb')
    nframes = wf.getnframes()
    framerate = wf.getframerate()
    print('Samplerate is:%s' % framerate)

    # 读取完整的帧数据到str_data中,这是一个string类型的数据
    str_data = wf.readframes(nframes)
    wf.close()

    # 将波形数据转换成数组
    wave_data = np.frombuffer(str_data, dtype=np.int16).astype(np.float32)
    # Scale the audio
    scale = 1./float(1 << ((8 * wf.getsampwidth()) - 1)) # from librosa
    wave_data *= scale
    #wave_data = np.fromstring(str_data, dtype=np.short)
    #wave_data = np.frombuffer(str_data, dtype=np.short)
    # 将wave_data数组改为2列,行数自动匹配
    wave_data.shape = -1,1
    # 将数组转置
    wave_data = wave_data.T
    return plot_frequencydomain(wave_data,framerate)


def plot_frequencydomain(wave_data,framerate):
    # 采样点数,修改采样点数和起始位置进行不同位置和长度的音频波形分析
    N =len(wave_data[0])
    start = 0  # 开始采样位置
    df = framerate / (N - 1)  # 分辨率
    freq = [df * n for n in range(0, N)]  # N个元素
    wave_data2 = wave_data[0][start:start + N]
    c =np.fft.fft(wave_data2) * 2 / N
    # 常规显示采样频率一半的频谱
    d = int(len(c) / 2)

    freqs = [fre for fre in freq]
    # 仅显示频率在6000以下的频谱
    while freqs[d] > 6000:
        d -= 10
    plt.plot(freqs[:d - 1], abs(c[:d - 1]), 'r')
    plt.show()

if __name__ == '__main__':
    load_file("1000HZ.wav")
    list1 = librosa_fft("1000HZ.wav")

使用wave读取,即调用代码中的 load_file("1000HZ.wav")得到结果:

 使用librosa读取,即调用代码中的 list1 = librosa_fft("1000HZ.wav")得到结果:

 发现频率相差两倍,不知道为什么?

然后又找到另一个音频1_16PCM.wav 分别用两种方法读取,得到的频率结果又相同

还没搞清楚为什么会有这样的区别

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

emollient

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值