我知道这似乎可能是ValueError的另一篇文章,但是请听我说一下,并了解我已经尝试使用Google搜索并浏览StackOverflow社区,以寻求针对我的问题的可行解决方案。
我目前正在尝试将解调后的样本传递给 sounddevice 模块,并使用其 callback 函数实时回放它。
错误:
audio_callback中的文件“ rtl-fm-cont.py”,第120行 outdata [:] =数据ValueError:无法将输入数组从形状(2048)广播到形状(2048,1)
我在下面附加了此代码的完整输出:
import numpy as np
#pythran export _mergesorted_1(float[:], int[:], int[:], int, bool)
#pythran export _mergesorted_1(int[:], int[:], int[:], int, bool)
def _mergesorted_1(DB, RB, SB, n, countequal):
N = len(DB)
K = ((N-n-1)>>1)<<1
for i in range(0, K, 2):
if DB[i] < DB[i+1] or (countequal and DB[i] == DB[i+1]):
SB[i] = i
SB[i+1] = i+1
RB[i+1] += 1
else:
SB[i] = i+1
SB[i+1] = i
if DB[i+1] < DB[i+1+n] or (countequal and DB[i+1] == DB[i+1+n]):
RB[i+1+n] += 1
for i in range(K, (N>>1)<<1, 2):
if DB[i] < DB[i+1] or (countequal and DB[i] == DB[i+1]):
SB[i] = i
SB[i+1] = i+1
RB[i+1] += 1
else:
SB[i] = i+1
SB[i+1] = i
if N & 1:
SB[N-1] = N-1
输出:
#!/usr/bin/env python
# library imports ...
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-d', '--device', type=int_or_str,
help='output device (numeric ID or substring)')
parser.add_argument('-b', '--blocksize', type=int, default=2048,
help='block size (default: %(default)s)')
parser.add_argument(
'-q', '--buffersize', type=int, default=20,
help='number of blocks used for buffering (default: %(default)s)')
args = parser.parse_args()
if args.blocksize == 0:
parser.error('blocksize must not be zero')
if args.buffersize < 1:
parser.error('buffersize must be at least 1')
q = queue.Queue(maxsize=args.buffersize)
event = threading.Event()
device_index = RtlSdr.get_device_index_by_serial('00000001')
class fmDemodulator(object):
# Called for each updates
def __init__(self, sdr=None):
self.sdr = sdr if sdr else RtlSdr(device_index)
def Demod(self, *args):
Fs = self.sdr.sample_rate
# Fc = self.sdr.center_freq
# Read IQ samples
samples = self.sdr.read_samples(4*12*2048)
print ('Fetching {} IQ samples from SDR #{}'.format(len(samples), device_index))
# Convert sampled data into numpy array
x1 = np.array(samples).astype("complex64")
# Downmixed Baseband Signal (Adjust offset to be centered)
offsetFreq = 0 # already centered
fc1 = np.exp(-1.0j*2.0*np.pi* offsetFreq/Fs*np.arange(len(x1)))
x2 = x1 * fc1
# Filter and downsample the FM Radio Signal
bwFM = 200000 # approx. 170 kHz for a single channel
decRate = int(Fs/bwFM)
x3 = signal.decimate(x2, decRate)
newFs = Fs/decRate
### Demodulate 200kHz FM Signal
# Polar discriminator
y4 = x3[1:] * np.conj(x3[:-1])
x4 = np.angle(y4)
# The de-emphasis filter
# Given a signal 'x4' (in a numpy array) with sampling rate newFS
d = newFs * 75e-6 # Calculate the # of samples to hit the -3dB point
x = np.exp(-1/d) # Calculate the decay between each sample
b = [1-x] # Create the filter coefficients
a = [1,-x]
x5 = signal.lfilter(b,a,x4)
# Find a decimation rate to achieve audio sampling rate between 44-48 kHz
audioFreq = 44100
dec_audio = int(newFs/audioFreq)
audioFs = newFs/dec_audio
x6 = signal.decimate(x5, dec_audio)
# Scale audio to adjust volume
x6 *= 10000 / np.max(np.abs(x6))
# debug
print ('decRate: {}, newFs : {}, dec_audio: {}'.format(decRate, newFs, dec_audio))
print ('Output audio: {} samples, audioFreq: {}, audioFs: {}'.format(len(x6), audioFreq, audioFs))
return x6
# https://python-sounddevice.readthedocs.io/en/0.3.6/examples.html
def audio_callback(outdata, frames, time, status):
"""This is called (from a separate thread) for each audio block."""
assert frames == args.blocksize
if status.output_underflow:
print('Output underflow: increase blocksize?', file=sys.stderr)
raise sd.CallbackAbort
assert not status
try:
data = q.get_nowait()
print(data)
print(data.dtype)
except queue.Empty:
print('Buffer is empty: increase buffersize?', file=sys.stderr)
raise sd.CallbackAbort
if len(data) < len(outdata):
outdata[:len(data)] = data
outdata[len(data):] = b'\x00' * (len(outdata) - len(data))
raise sd.CallbackStop
else:
outdata[:] = data
def main():
sdr = RtlSdr(device_index)
fm = fmDemodulator(sdr)
# SDR Configurations
sdr.sample_rate = int(2.4e6) # Hz
sdr.center_freq = int(102e6) # Hz
sdr.freq_correction = 77 # PPM +- 20
sdr.gain = 'auto'
samplerate = 50000
channels = 1
try:
for _ in range(args.buffersize):
data = fm.Demod()
if not np.any(data):
break
q.put_nowait(data) # pre-fill queue
stream = sd.OutputStream(
samplerate=samplerate, blocksize=args.blocksize,
device=args.device, channels=channels, dtype='int16',
callback=audio_callback, finished_callback=event.set)
with stream:
timeout = args.blocksize * args.buffersize / samplerate
while np.any(data): # while data
data = fm.Demod()
q.put(data, timeout=timeout)
event.wait() # Wait until playback is finished
except KeyboardInterrupt:
parser.exit('\nInterrupted by user')
except queue.Full:
# A timeout occured, i.e. there was an error in the callback
parser.exit(1)
except Exception as e:
parser.exit(type(e).__name__ + ': ' + str(e))
我们将非常感谢您的帮助。 预先谢谢你。