【问题标题】:How to get a list of frequencies in a wav file如何获取 wav 文件中的频率列表
【发布时间】:2021-03-18 22:56:59
【问题描述】:

我正在尝试解码一些音频,这些音频基本上是直接转换为二进制的两个频率(0 为 200hz,1 为 800hz)。 A sample of the audio

此示例翻译为“1001011”。 还有第三个频率是 1600hz 作为位之间的分频器。

我找不到任何有用的东西,我确实找到了一些东西,但它要么已经过时,要么直接不起作用,我真的很绝望。

我制作了一个可以为这种编码生成音频的示例代码(用于测试解码器):

import math
import wave
import struct

audio = []
sample_rate = 44100.0

def split(word):
    return [char for char in word]

def append_sinewave(
        freq=440.0,
        duration_milliseconds=10,
        volume=1.0):
    global audio
    num_samples = duration_milliseconds * (sample_rate / 1000.0)
    for x in range(int(num_samples)):
        audio.append(volume * math.sin(2 * math.pi * freq * ( x / sample_rate )))
    return
def save_wav(file_name):
    wav_file=wave.open(file_name,"w")
    nchannels = 1
    sampwidth = 2
    nframes = len(audio)
    comptype = "NONE"
    compname = "not compressed"
    wav_file.setparams((nchannels, sampwidth, sample_rate, nframes, comptype, compname))
    for sample in audio:
        wav_file.writeframes(struct.pack('h', int( sample * 32767.0 )))
    wav_file.close()
    return
print("Input data!\n(binary)")
data=input(">> ")
dataL = []
dataL = split(data)
for x in dataL:
    if x == "0":
        append_sinewave(freq=200)
    elif x == "1":
        append_sinewave(freq=800)
    append_sinewave(freq=1600,duration_milliseconds=5)
    print("Making "+str(x)+" beep")


print("\nWriting to file this may take a while!")
save_wav("output.wav")

感谢您提前提供帮助!

【问题讨论】:

  • 您的代码的输入是什么?你在寻找什么输出?
  • 编码器接收一个二进制字符串,并用编码的数据制作一个 wav 文件。解码器接收音频并从中恢复原始二进制字符串。
  • 我希望能得到更多。 “二进制字符串”是什么意思?每个样本是多少位?

标签: python decode wav decoding decoder


【解决方案1】:

我想我明白你在尝试什么。从您的编码器脚本中,我假设每个 bit 在您的波形文件中转换为 10 毫秒,并以 5ms 1600hz 音调作为一种分隔符。如果这些持续时间是固定的,您可以简单地使用scipynumpy 来分割音频并解码每个片段。

鉴于您上面的编码器脚本为字节串生成一个 105ms (7 * 15ms) 单声道output.wav1001011,如果要忽略定界频率,我们应该旨在返回一个表示每个频率的列表bit:

[800, 200, 200, 800, 200, 800, 800]

我们可以使用scipy读入音频,并使用numpy对音频片段进行FFT,得到每个片段的频率:

from scipy.io import wavfile as wav

import numpy as np

rate, data = wav.read('./output.wav')

# 15ms chunk includes delimiting 5ms 1600hz tone
duration = 0.015

# calculate the length of our chunk in the np.array using sample rate
chunk = int(rate * duration)

# length of delimiting 1600hz tone
offset = int(rate * 0.005)

# number of bits in the audio data to decode
bits = int(len(data) / chunk)

def get_freq(bit):
    # start position of the current bit
    strt = (chunk * bit) 
    
    # remove the delimiting 1600hz tone
    end = (strt + chunk) - offset
    
    # slice the array for each bit
    sliced = data[strt:end]

    w = np.fft.fft(sliced)
    freqs = np.fft.fftfreq(len(w))

    # Find the peak in the coefficients
    idx = np.argmax(np.abs(w))
    freq = freqs[idx]
    freq_in_hertz = abs(freq * rate)
    return freq_in_hertz

decoded_freqs = [get_freq(bit) for bit in range(bits)]

产量

[800.0, 200.0, 200.0, 800.0, 200.0, 800.0, 800.0]

转换为位/字节:

bitsarr = [1 if freq == 800 else 0 for freq in decoded_freqs]

byte_array = bytearray(bitsarr)
decoded = bytes(a_byte_array)
print(decoded, type(decoded))

产量

b'\x01\x00\x00\x01\x00\x01\x01' <class 'bytes'>

有关推导峰值频率的更多信息,请参阅this question

【讨论】:

  • YESSSSS!!!!!!非常感谢,我感激不尽!
  • 听起来是一个有趣的项目,如果您愿意,可以在评论或原始问题中发布结果 - 喜欢了解更多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2016-01-20
  • 1970-01-01
相关资源
最近更新 更多