创建GNURadio源块:如何调整采样率

时间:2016-10-20 13:26:39

标签: python gnuradio gnuradio-companion

我试图在GNU无线电中为Analog Discovery 2示波器实现自定义源块。我已经有一个工作的python脚本来记录从Analog Discovery 2设备到WAV文件的样本(问题末尾的代码)。

我希望能够直接在GNUradio配套中连接此示例源。我已按照the official tutorial创建自定义块以生成我的块的模板代码:

import numpy
from gnuradio import gr

class AnalogDiscovery2(gr.sync_block):

    def __init__(self, sample_rate):
        gr.sync_block.__init__(self,
            name="Analog Discovery 2",
            in_sig=None,
            out_sig=[numpy.float32])
        self.sample_rate = sample_rate


    def work(self, input_items, output_items):
        out = output_items[0]
        # <+signal processing here+>
        out[:] = whatever
        return len(output_items[0])

我知道我必须修改work函数来获取样本并将它们复制到out变量,但是我想知道如何调整采样率?我不知道如何调用work函数,它的时间是什么。如何设置采样率?

将样本记录到WAV文件中的Python代码:

from ctypes import *
from dwfconstants import *
import math
import time
import matplotlib.pyplot as plt
import sys
import wave
import struct

if sys.platform.startswith("win"):
    dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
    dwf = cdll.LoadLibrary("libdwf.so")

#declare ctype variables
hdwf = c_int()
sts = c_byte()
hzAcq = c_double(48000)
nSamples = 96000
rgdSamples = (c_double*nSamples)()
cAvailable = c_int()
cLost = c_int()
cCorrupted = c_int()
fLost = 0
fCorrupted = 0

#print DWF version
version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
print "DWF Version: "+version.value

#open device
print "Opening first device"
dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))

if hdwf.value == hdwfNone.value:
    szerr = create_string_buffer(512)
    dwf.FDwfGetLastErrorMsg(szerr)
    print szerr.value
    print "failed to open device"
    quit()

print "Preparing to read sample..."

#print "Generating sine wave..."
#dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_bool(True))
#dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
#dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(1))
#dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(2))
#dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_bool(True))

# enable positive supply
dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(True)) 
# set voltage to 3 V
dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(3.0)) 
# enable negative supply
dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(0), c_double(True)) 
# set voltage to -1 V
dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(1), c_double(-1.0)) 
# master enable
dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))

#set up acquisition
dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_bool(True))
dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(0.1))
dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(nSamples/hzAcq.value))

#wait at least 2 seconds for the offset to stabilize
time.sleep(2)

#begin acquisition
dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
print "   waiting to finish"

cSamples = 0

while cSamples < nSamples:
    dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
    if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
        # Acquisition not yet started.
        continue

    dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))

    cSamples += cLost.value

    if cLost.value :
        fLost = 1
    if cCorrupted.value :
        fCorrupted = 1

    if cAvailable.value==0 :
        continue

    if cSamples+cAvailable.value > nSamples :
        cAvailable = c_int(nSamples-cSamples)

    # get samples
    dwf.FDwfAnalogInStatusData(hdwf, c_int(0), byref(rgdSamples, 8*cSamples), cAvailable)
    cSamples += cAvailable.value


print "Recording finished"
if fLost:
    print "Samples were lost! Reduce frequency"
if cCorrupted:
    print "Samples could be corrupted! Reduce frequency"

#f = open("record.bin", "w")
#for v in rgdSamples:
#    f.write("%s\n" % v)
#f.close()

# Write samples to file
wav_output = wave.open('record.wav', 'w')
wav_output.setparams((1, 2, 48000, nSamples, 'NONE', 'not compressed'))
values = []
for v in rgdSamples:
    packed_value = struct.pack('h', 32768*v)
    values.append(packed_value)

value_str = ''.join(values)
wav_output.writeframes(value_str)
wav_output.close()

1 个答案:

答案 0 :(得分:1)

你有一种误解。

对于GNU Radio,采样率不是一个有意义的概念。 GNU Radio块尽可能快地安排;这意味着重复调用源块,直到输出缓冲区已满。

“挂钟”与处理样品的速度无关。

例如,信号源仅使用采样率信息来计算一段时间内样本的数量。一个正弦的。信号源配置为以500个价格的采样率生成频率为10的正弦相同的样本,就像将其配置为50的频率和2500的采样率一样。绝对没有行为差。

我只能强调GNU Radio没有任何采样率的概念。块之间传递的信号只是数字序列。原始音频以特定速率采样的事实可能是正确参数化处理样本的块所必需的,但这并不是样本固有的。

顺便说一句,没有理由编写自己的wav文件源:gr-audio已包含一个。