[英]How to get a list of frequencies in a wav file
I'm trying to decode some audio which is basically two frequencies (200hz for a 0 and 800hz for 1) that directly translates directly to binary.我正在尝试解码一些音频,这些音频基本上是两个频率(0 为 200hz,1 为 800hz),直接转换为二进制。 A sample of the audio
音频样本
This sample translates to "1001011".此示例翻译为“1001011”。 There is a third frequency that is 1600hz as a dividor between the bits.
第三个频率是 1600hz,作为位之间的分频器。
I can't find anything that works i did find a few things but it either was outdated or just straight up not working i'm really despaired.我找不到任何有用的东西我确实找到了一些东西,但它要么已经过时,要么直接不起作用,我真的很绝望。
I made a sample code that can generate audio for this encoding (to test the decoder):我制作了一个可以为此编码生成音频的示例代码(以测试解码器):
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")
Thanks for helping in advance!感谢您提前提供帮助!
I think I understand what you are attempting.我想我明白你在尝试什么。 From your encoder script I assume that each
bit
translates to 10 milliseconds in your wave file, with a 5ms 1600hz tone as a kind of delimiter.从您的编码器脚本中,我假设每个
bit
在您的波形文件中转换为 10 毫秒,其中 5 毫秒 1600 赫兹音调作为一种分隔符。 If these durations are fixed, you could simply use scipy
and numpy
to segment the audio and decode each segment.如果这些持续时间是固定的,您可以简单地使用
scipy
和numpy
来分割音频并解码每个片段。
Given your encoder script above to generate a 105ms (7 * 15ms) mono output.wav
for the bytestring: 1001011
and if the delimiting frequencies are to be ignored, we should aim to return a list representing the frequencies for each bit
:给定上面的编码器脚本以生成 105ms (7 * 15ms) mono
output.wav
的字节串: 1001011
,如果要忽略定界频率,我们应该返回一个代表每个bit
频率的列表:
[800, 200, 200, 800, 200, 800, 800]
We can read in the audio using scipy
and perform the FFT on segments of the audio using numpy
to get the frequencies of each segment:我们可以使用
numpy
读取音频,并使用scipy
对音频片段执行 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)]
yields产量
[800.0, 200.0, 200.0, 800.0, 200.0, 800.0, 800.0]
To convert to bits/bytes:要转换为位/字节:
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))
yields产量
b'\x01\x00\x00\x01\x00\x01\x01' <class 'bytes'>
Further information about deriving the peak frequency see this question有关推导峰值频率的更多信息,请参阅此问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.