def __init__(self, Fs, Fc, upsample_factor): self.upsample_factor = upsample_factor self.order = 6 self.y_hist = np.zeros(self.order) self.lowpass = iir.lowpass(.8 / upsample_factor) self.i = 0 self.s = -1j * 2 * np.pi * Fc / Fs
def init(self): super(Downconverter, self).init() self.next = self.kwarg('next', None) self.iir_state = np.zeros(6) self.iir = iir.lowpass(.8 / upsample_factor) self.i = 0 self.s = -1j * 2 * np.pi * loopback_Fc / loopback_Fs
def downconvert(source, channel): i = 0 lp = iir.lowpass(.45/channel.upsample_factor, order=6) for y in source: smoothed = lp(y * np.exp(-1j*2*np.pi*channel.Fc/channel.Fs * np.r_[i:i+y.size])) yield smoothed[-i%channel.upsample_factor::channel.upsample_factor] i += y.size
def init(self): super(Downconverter, self).init() self.next = self.kwarg('next', None) self.iir_state = np.zeros(6) self.iir = iir.lowpass(.8/upsample_factor) self.i = 0 self.s = -1j * 2 * np.pi * loopback_Fc / loopback_Fs
def __init__(self, Fs, Fc, upsample_factor): self.upsample_factor = upsample_factor self.order = 6 self.y_hist = np.zeros(self.order) self.lowpass = iir.lowpass(.8/upsample_factor) self.i = 0 self.s = -1j * 2 * np.pi * Fc / Fs
def processInput(input, loopback_Fs, loopback_Fc, upsample_factor): input = input * np.exp( -1j * 2 * np.pi * np.arange(input.size) * loopback_Fc / loopback_Fs) order = 6 input = iir.lowpass(.8 / upsample_factor, order=order)(np.r_[np.zeros(order), input])[order:] input = input[(np.arange(input.size / upsample_factor) * upsample_factor).astype(int)] return input
def encodeBlurt(source, channel): cutoff = (Nsc_used/2 + .5)/nfft lp1 = iir.lowpass(cutoff/channel.upsample_factor, order=6, method='Ch', ripple=-.021) lp2 = lp1.copy() baseRate = rates[0xb] k = 0 for octets in source: # prepare header and payload bits rateEncoding = 0xb rate = rates[rateEncoding] data_bits = (octets[:,None] >> np.arange(8)[None,:]).flatten() & 1 data_bits = np.r_[np.zeros(16, int), data_bits, (~CRC(data_bits) >> np.arange(32)[::-1]) & 1] plcp_bits = ((rateEncoding | ((octets.size+4) << 5)) >> np.arange(18)) & 1 plcp_bits[-1] = plcp_bits.sum() & 1 # OFDM modulation subcarriers = np.vstack((subcarriersFromBits(plcp_bits, baseRate, 0 ), subcarriersFromBits(data_bits, rate, 0x5d))) pilotPolarity = np.resize(scrambler[0x7F], subcarriers.shape[0]) symbols = np.zeros((subcarriers.shape[0],nfft), complex) symbols[:,dataSubcarriers] = subcarriers symbols[:,pilotSubcarriers] = pilotTemplate * (1. - 2.*pilotPolarity)[:,None] ts_tile_shape = (ncp*ts_reps+nfft-1)//nfft + ts_reps + 1 symbols_tile_shape = (1, (ncp+nfft-1)//nfft + 1 + 1) sts_time = np.tile(np.fft.ifft(sts_freq), ts_tile_shape)[-ncp*ts_reps%nfft:-nfft+1] lts_time = np.tile(np.fft.ifft(lts_freq), ts_tile_shape)[-ncp*ts_reps%nfft:-nfft+1] symbols = np.tile(np.fft.ifft(symbols ), symbols_tile_shape)[:,-ncp%nfft:-nfft+1] # temporal smoothing subsequences = [sts_time, lts_time] + list(symbols) output = np.zeros(sum(map(len, subsequences)) - len(subsequences) + 1, complex) i = 0 for x in subsequences: j = i + len(x)-1 output[i] += .5*x[0] output[i+1:j] += x[1:-1] output[j] += .5*x[-1] i = j output = np.vstack((output, np.zeros((channel.upsample_factor-1, output.size), output.dtype))) output = output.T.flatten()*channel.upsample_factor output = lp2(lp1(np.r_[np.zeros(200), output, np.zeros(200)])) # modulation and pre-emphasis Omega = 2*np.pi*channel.Fc/channel.Fs output = (output * np.exp(1j* Omega * np.r_[k:k+output.size])).real k += output.size for i in range(preemphasisOrder): output = np.diff(np.r_[output,0]) output *= abs(np.exp(1j*Omega)-1)**-preemphasisOrder # stereo beamforming reduction delay = np.zeros(stereoDelay*channel.Fs) yield np.vstack((np.r_[delay, output], np.r_[output, delay])).T
def __init__(self): self.Fs = Fs = 96e3 self.pulse_low = 10e3 self.pulse_high = 30e3 self.pulse_duration = int(.1 * Fs) self.display_duration = 3. self.spacing = spacing = int(.02 * Fs) simultaneous_pulses = (self.pulse_duration+2*spacing-1) // (2*spacing) self.base_chirp = chirp(self.pulse_low/Fs, self.pulse_high/Fs, self.pulse_duration) pulse = self.base_chirp.real pulse *= np.clip(np.arange(self.pulse_duration, dtype=float)/(Fs*.025), 0, 1) pulse *= np.clip(-np.arange(-self.pulse_duration, 0, dtype=float)/(Fs*.025), 0, 1) mono_timing = np.tile(np.r_[1, np.zeros(spacing*2-1)], 3*simultaneous_pulses) mono = scipy.signal.fftconvolve(mono_timing, pulse, 'full')[(simultaneous_pulses-1)*spacing*2:simultaneous_pulses*spacing*2] self.output = np.tile(np.vstack((mono, np.roll(mono, spacing))).T, (20,1)) self.lpf = iir.lowpass((self.pulse_high-self.pulse_low)/Fs/2) cs = 1116.44 # feet/sec self.columns = int(self.display_duration*Fs) // (spacing*2) self.buffer = np.zeros((2, spacing, self.columns*2), np.uint16) self.window_phase = 0 self.input_fragment = np.zeros(0, np.complex64) self.extent = (0, self.display_duration, -spacing*.1/Fs*cs/2, spacing*.9/Fs*cs/2) self.i = 0 self.phase_locked = None super().__init__(channels=2, outBufSize=16384, inBufSize=8192) self.fig.delaxes(self.ax) self.ax1 = self.fig.add_subplot(1,2,1) self.im1 = self.ax1.imshow(self.buffer[0], vmin=0., vmax=10., extent=self.extent, aspect='auto', interpolation='nearest') self.ax1.set_xlim(self.extent[:2]) self.ax1.set_ylim(self.extent[2:]) self.ax1.grid() self.ax2 = self.fig.add_subplot(1,2,2) self.im2 = self.ax2.imshow(self.buffer[1], vmin=0., vmax=10., extent=self.extent, aspect='auto', interpolation='nearest') self.ax2.set_xlim(self.extent[:2]) self.ax2.set_ylim(self.extent[2:]) self.ax2.grid() self.ax1.patch.set_visible(False) self.ax2.patch.set_visible(False) self.fig.patch.set_facecolor('k') audio.stream.set_backgroundcolor(self.ax1, 'k') audio.stream.set_foregroundcolor(self.ax1, 'w') audio.stream.set_backgroundcolor(self.ax2, 'k') audio.stream.set_foregroundcolor(self.ax2, 'w') self.cm = pl.get_cmap('jet')(np.arange(0,65536)/65535., bytes=True)
def prepareMaskNoise(fn, Fs, Fc, upsample_factor): f = wave.open(fn) nframes = f.getnframes() dtype = [None, np.uint8, np.int16, None, np.int32][f.getsampwidth()] frames = np.fromstring(f.readframes(nframes), dtype).astype(float) frames = frames.reshape(nframes, f.getnchannels()) frames = frames.mean(1) frames = util.upsample(frames, Fs / f.getframerate()) frames /= np.amax(np.abs(frames)) # band-stop filter for data frames *= np.exp(-1j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = iir.highpass(.8 / upsample_factor)(frames) frames *= np.exp(2j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = iir.highpass(.8 / upsample_factor)(frames) frames *= np.exp(-1j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = frames.real # look for beginning and end of noise envelope = iir.lowpass(.01)(np.r_[np.zeros(6), np.abs(frames)])[6:] start = np.where(envelope > np.amax(envelope) * .01)[0][0] end = np.where(envelope > np.amax(envelope) * 1e-3)[0][-1] return frames[start:end]
def prepareMaskNoise(fn, Fs, Fc, upsample_factor): f = wave.open(fn) nframes = f.getnframes() dtype = [None, np.uint8, np.int16, None, np.int32][f.getsampwidth()] frames = np.fromstring(f.readframes(nframes), dtype).astype(float) frames = frames.reshape(nframes, f.getnchannels()) frames = frames.mean(1) frames = util.upsample(frames, Fs/f.getframerate()) frames /= np.amax(np.abs(frames)) # band-stop filter for data frames *= np.exp(-1j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = iir.highpass(.8/upsample_factor)(frames) frames *= np.exp(2j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = iir.highpass(.8/upsample_factor)(frames) frames *= np.exp(-1j * 2 * np.pi * np.arange(frames.size) * Fc / Fs) frames = frames.real # look for beginning and end of noise envelope = iir.lowpass(.01)(np.r_[np.zeros(6), np.abs(frames)])[6:] start = np.where(envelope > np.amax(envelope)*.01)[0][0] end = np.where(envelope > np.amax(envelope)*1e-3)[0][-1] return frames[start:end]
def processWave(fn): signal, Fs = util.readwave(fn) signal = np.r_[np.zeros(Fs / 2), signal] alternation_interval = Fs * 2 steady_interval = Fs * 1.5 # we need to classify the sections of noise and silence, identify the # steady-state intervals, FFT them, and label them, then write out the results. signal *= 1. / signal.std() def downsample(x, ratio): order = 6 return iir.lowpass(1. / (2 * ratio), method='Ch -.2', order=order)(np.r_[np.zeros(order), x])[order::ratio] def peak_detect(input, window_size): # look for points outstanding in their neighborhood # by explicit comparison l = window_size M = scipy.linalg.toeplitz(np.r_[input, np.zeros(2 * l)], np.zeros(2 * l + 1)).T ext_input = np.r_[np.zeros(l), input, np.zeros(l)] M[:l] = M[:l] < ext_input M[l + 1:] = M[l + 1:] < ext_input M[l] = True return np.where(M.all(0))[0] - l ratio = 32 * 15 * 25 envelope = iir.lowpass(.125)(downsample( downsample(downsample(np.abs(signal), 32), 15), 25)) peaks = peak_detect(envelope, 8) * ratio - 77840 radius = steady_interval / 2 subintervals = 75 intervals = ([], []) S_Y_samples = [] S_N_samples = [] for p in peaks: if p < radius or p + alternation_interval + radius >= signal.size: continue intervals[0].append((p - radius, p + radius)) noise = signal[p - radius:p + radius] noise = np.fft.fft(noise.reshape(subintervals, steady_interval / subintervals), axis=1) S_Y_samples.append(noise.var(0)) intervals[1].append((p + alternation_interval - radius, p + alternation_interval + radius)) silence = signal[p + alternation_interval - radius:p + alternation_interval + radius] silence = np.fft.fft(silence.reshape(subintervals, steady_interval / subintervals), axis=1) S_N_samples.append(silence.var(0)) bins = steady_interval / subintervals / 2 # note: S_Y = P + N, S_N = N, so S_Y/S_N = 1 + P/N capacity = np.array([ np.log2(np.clip(S_Y / S_N, 1., np.inf)) for S_Y, S_N in zip(S_Y_samples, S_N_samples) ]).mean(0)[:bins] S_X = bins * 2 * .1**2 S_H = np.array([ np.clip(S_Y - S_N, 0, np.inf) / S_X for S_Y, S_N in zip(S_Y_samples, S_N_samples) ])[:, :bins] H_mag = S_H.mean(0)**.5 S_Y = np.array(S_Y_samples).mean(0)[:bins] S_N = np.array(S_N_samples).mean(0)[:bins] df = Fs / float(steady_interval / subintervals) f = df * np.arange(bins) visualize = False if visualize: pl.figure() pl.subplot(221) pl.plot(f, 10 * np.log10(S_Y - S_N)) pl.plot(f, 10 * np.log10(S_N)) pl.xlim(0, f.max()) pl.subplot(223) pl.plot(f, capacity) pl.xlim(0, f.max()) pl.xlabel('Frequency (Hz)') pl.ylabel('Capacity (bits/s/Hz)') pl.subplot(122) pl.plot(f, capacity.cumsum() * df) pl.xlim(0, f.max()) test_synchronization = False if test_synchronization: pl.clf() lp = lambda x: iir.lowpass(.005)(np.r_[np.zeros(6), x])[6:] pl.plot(lp(np.abs(signal)) * .5) pl.plot(np.arange(envelope.size) * ratio - 77840, envelope) for x in peaks: pl.gca().axvline(x, color='k') noise_interval = np.zeros(signal.size, bool) for start, end in intervals[0]: noise_interval[start:end] = True silence_interval = np.zeros(signal.size, bool) for start, end in intervals[1]: silence_interval[start:end] = True import matplotlib.transforms as mtransforms ax = pl.gca() trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes) ax.fill_between(np.arange(signal.size), 0, 1, where=noise_interval, facecolor='red', alpha=0.5, transform=trans) ax.fill_between(np.arange(signal.size), 0, 1, where=silence_interval, facecolor='magenta', alpha=0.5, transform=trans) return df, H_mag, S_N, capacity, len(peaks)
def downsample(x, ratio): order = 6 return iir.lowpass(1. / (2 * ratio), method='Ch -.2', order=order)(np.r_[np.zeros(order), x])[order::ratio]
def processWave(fn): signal, Fs = util.readwave(fn) signal = np.r_[np.zeros(Fs/2), signal] alternation_interval = Fs*2 steady_interval = Fs*1.5 # we need to classify the sections of noise and silence, identify the # steady-state intervals, FFT them, and label them, then write out the results. signal *= 1./signal.std() def downsample(x, ratio): order = 6 return iir.lowpass(1./(2*ratio), method='Ch -.2', order=order)(np.r_[np.zeros(order), x])[order::ratio] def peak_detect(input, window_size): # look for points outstanding in their neighborhood # by explicit comparison l = window_size M = scipy.linalg.toeplitz(np.r_[input, np.zeros(2*l)], np.zeros(2*l+1)).T ext_input = np.r_[np.zeros(l), input, np.zeros(l)] M[:l] = M[:l] < ext_input M[l+1:] = M[l+1:] < ext_input M[l] = True return np.where(M.all(0))[0] - l ratio = 32*15*25 envelope = iir.lowpass(.125)(downsample(downsample(downsample(np.abs(signal), 32), 15), 25)) peaks = peak_detect(envelope, 8) * ratio - 77840 radius = steady_interval/2 subintervals = 75 intervals = ([], []) S_Y_samples = [] S_N_samples = [] for p in peaks: if p < radius or p + alternation_interval + radius >= signal.size: continue intervals[0].append((p-radius,p+radius)) noise = signal[p-radius:p+radius] noise = np.fft.fft(noise.reshape(subintervals, steady_interval/subintervals), axis=1) S_Y_samples.append(noise.var(0)) intervals[1].append((p+alternation_interval-radius,p+alternation_interval+radius)) silence = signal[p+alternation_interval-radius:p+alternation_interval+radius] silence = np.fft.fft(silence.reshape(subintervals, steady_interval/subintervals), axis=1) S_N_samples.append(silence.var(0)) bins = steady_interval/subintervals/2 # note: S_Y = P + N, S_N = N, so S_Y/S_N = 1 + P/N capacity = np.array([np.log2(np.clip(S_Y/S_N, 1., np.inf)) for S_Y, S_N in zip(S_Y_samples, S_N_samples)]).mean(0)[:bins] S_X = bins * 2 * .1**2 S_H = np.array([np.clip(S_Y-S_N,0,np.inf)/S_X for S_Y, S_N in zip(S_Y_samples, S_N_samples)])[:,:bins] H_mag = S_H.mean(0)**.5 S_Y = np.array(S_Y_samples).mean(0)[:bins] S_N = np.array(S_N_samples).mean(0)[:bins] df = Fs/float(steady_interval/subintervals) f = df*np.arange(bins) visualize = False if visualize: pl.figure() pl.subplot(221) pl.plot(f, 10*np.log10(S_Y-S_N)) pl.plot(f, 10*np.log10(S_N)) pl.xlim(0, f.max()) pl.subplot(223) pl.plot(f, capacity) pl.xlim(0, f.max()) pl.xlabel('Frequency (Hz)') pl.ylabel('Capacity (bits/s/Hz)') pl.subplot(122) pl.plot(f, capacity.cumsum()*df) pl.xlim(0, f.max()) test_synchronization = False if test_synchronization: pl.clf() lp = lambda x:iir.lowpass(.005)(np.r_[np.zeros(6), x])[6:] pl.plot(lp(np.abs(signal))*.5) pl.plot(np.arange(envelope.size) * ratio - 77840, envelope) map(lambda x:pl.gca().axvline(x, color='k'), peaks) noise_interval = np.zeros(signal.size, bool) for start, end in intervals[0]: noise_interval[start:end] = True silence_interval = np.zeros(signal.size, bool) for start, end in intervals[1]: silence_interval[start:end] = True import matplotlib.transforms as mtransforms ax = pl.gca() trans = mtransforms.blended_transform_factory(ax.transData, ax.transAxes) ax.fill_between(np.arange(signal.size), 0, 1, where=noise_interval, facecolor='red', alpha=0.5, transform=trans) ax.fill_between(np.arange(signal.size), 0, 1, where=silence_interval, facecolor='magenta', alpha=0.5, transform=trans) return df, H_mag, S_N, capacity, len(peaks)
def downsample(x, ratio): order = 6 return iir.lowpass(1./(2*ratio), method='Ch -.2', order=order)(np.r_[np.zeros(order), x])[order::ratio]
def processInput(input, loopback_Fs, loopback_Fc, upsample_factor): input = input * np.exp(-1j * 2 * np.pi * np.arange(input.size) * loopback_Fc / loopback_Fs) order = 6 input = iir.lowpass(.8/upsample_factor, order=order)(np.r_[np.zeros(order), input])[order:] input = input[(np.arange(input.size/upsample_factor) * upsample_factor).astype(int)] return input
# trajectory is in meters cs = 340. # m/s x[:,0] = 0 x[:,27:38] = 0 y = np.tile(np.fft.ifft(x, axis=1), (1,3))[:,48:129] y[1:,0] = (y[1:,0] + y[:-1,-1]) * .5 y = upsample.upsample(y[:,:80].flatten(), upsample_factor) y = (y * np.exp(1j*2*np.pi*Fc*np.arange(y.size)/Fs)).real pl.figure() _=pl.specgram(y+n, NFFT=64*upsample_factor, noverlap=-16*upsample_factor, interpolation='nearest', Fs=Fs) t0 = np.arange(y.size)/Fs t = t0 - trajectory / cs y2 = np.interp(t, t0, y.real) y2 = iir.lowpass(1./upsample_factor)(y2 * np.exp(-1j*2*np.pi*Fc*np.arange(y.size)/Fs))[::upsample_factor/4] pl.figure() _=pl.specgram(y2+n[:y2.size], NFFT=64*4, noverlap=-16*4, interpolation='nearest', Fs=Fs/(upsample_factor/4)) noisy_y2 = y2 + n[:y2.size] z = (np.ediff1d(y2, to_end=0.).conj() * y2 * (1j * np.pi * 2)).real w = ((np.arange(64*4) + 32*4) % (64*4) - 32*4) w = np.where(abs(w) < 32, w, 0) e = abs(np.fft.fft((y2+n[:y2.size]).reshape(-1,80*4)[:,16*4:] * np.blackman(64*4), axis=1))**2 pl.clf() _=pl.specgram(y2+n[:y2.size], NFFT=64*4, noverlap=-16*4, interpolation='nearest', Fs=Fs/(upsample_factor/4)) pl.plot(np.arange(100)*80*upsample_factor/Fs, 1200 + .1 *(e*w).sum(1))