2016-10-20 72 views
0

我試圖在GNU無線電中爲模擬發現2示波器實現自定義源塊。我已經有了一個工作的python腳本,可以將來自Analog Discovery 2設備的樣本記錄到WAV文件(問題結尾的代碼)。創建GNURadio源塊:如何調整採樣率

我希望能夠直接在GNUradio companion中連接此示例源。我已經按照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函數,它的時間是什麼。我如何設置採樣率?

Python代碼的記錄樣本爲WAV文件:

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

你有一個誤解。

採樣率對於GNU Radio來說並不是一個有意義的概念。儘可能快地安排GNU無線電塊;這意味着一個源塊被重複調用,直到輸出緩衝區滿了。

「掛鐘」與樣品處理速度無關。

例如,信號源僅使用採樣率信息來計算有多少個樣本的時間段例如。一個正弦。信號源配置爲以500的採樣率產生正弦頻率爲10的正弦曲線恰好爲相同的採樣,如果將其配置爲50的頻率和2500的採樣率,則絕對沒有行爲差異。

我只能強調GNU收音機沒有任何採樣率的概念。在這些塊之間傳遞的信號只是序號。原始音頻以特定速率進行採樣的事實可能需要正確參數化處理樣本的塊,但這並不是樣本固有的。

順便說一下,沒有理由編寫自己的wav文件源:gr-audio已經包含了一個。

+0

我不想寫我自己的wav文件源:我想讓我的USB示波器將它的樣本放到GNU收音機中。示波器的採樣率取決於「掛鐘」。 – Vincz777

+0

是的,那麼它定義了樣本進入流程圖的速率。在您的work()功能中,您只需調用您必須調用的任何函數以將樣本從振盪器中取出。 GNU Radio並不關心它在GNU Radio上的採樣率,而只是產生一堆樣本。 –