我知道这可能是另一篇ValueError帖子,但请听我说完,并理解我已经尝试在谷歌上搜索和浏览StackOverflow社区,以找到解决我问题的可行方案。
我目前正试图将我的解调样本传递到声音设备模块,并使用其回调功能实时播放。
错误:
文件"rtl-fm-cont.py",第120行,在audio_callback中outdata[:]=数据值错误:无法将输入数组从形状(2048(广播到形状(2048,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))
输出:
Output audio: 2048 samples, audioFreq: 44100, audioFs: 50000.0
Fetching 98304 IQ samples from SDR #0
...
Fetching 98304 IQ samples from SDR #0
decRate: 12, newFs : 200000.0, dec_audio: 4
Output audio: 2048 samples, audioFreq: 44100, audioFs: 50000.0
Fetching 98304 IQ samples from SDR #0
[ 627.05045796 1835.36815837 3381.16496121 ... 401.43836645
-1156.07050642 -1291.0900775 ]
float64
From cffi callback <function _StreamBase.__init__.<locals>.callback_ptr at 0x10eabbea0>:
Traceback (most recent call last):
File "/Users/user/.local/lib/python3.6/site-packages/sounddevice.py", line 741, in callback_ptr
return _wrap_callback(callback, data, frames, time, status)
File "/Users/user/.local/lib/python3.6/site-packages/sounddevice.py", line 2517, in _wrap_callback
decRate: 12, newFs : 200000.0, dec_audio: 4
Output audio: 2048 samples, audioFreq: 44100, audioFs: 50000.0
callback(*args)
File "rtl-fm-cont.py", line 120, in audio_callback
outdata[:] = data
ValueError: could not broadcast input array from shape (2048) into shape (2048,1)
Fetching 98304 IQ samples from SDR #0
decRate: 12, newFs : 200000.0, dec_audio: 4
Output audio: 2048 samples, audioFreq: 44100, audioFs: 50000.0
非常感谢您的帮助。提前谢谢。
看起来很简单:
outdata[:] = data.reshape(2048,1)
numpy.reshape
修复了问题。