Skip to main content

CW FIR Filter



This Python module defines a Waveform class with methods sinewave and noise. Sinewave generates a specified frequency and noise generates samples with specified standard deviation. The constructor requires the duration for both methods to be specified. Class variables are the sampling rate and the number of channels. The packed strings and the signal and noise lists are available. main() adds these and uses Bandpass (from bpf_class - Kaiser window response above) to filter the unpacked samples, using lfilter from audioop. Audio before and after filtering is played and recorded to file.

#!/usr/bin/python

import wave, struct, math, audioop
from alsaaudio import *
import signal, sys, getopt
from numpy.random import normal
from scipy.signal import lfilter
from bpf_class import Bandpass


class Waveform:
    " Waveform Class Generates different waveforms with duration (Sec) length "

    def __init__(self, duration):
        self.rate = 8000         # frame rate
        self.channels = 1        # mono stereo etc
        self.frames = int(duration * self.rate) # number of samples (2 bytes)

        # sound card device initialization (alsa module)
        self.out = PCM(type=PCM_PLAYBACK, mode=PCM_NONBLOCK, card='default')

        # parameters

        self.out.setchannels(self.channels)
        self.out.setrate(self.rate)

        # Signed 16 bit samples for each channel (Little Endian byte order)
        self.out.setformat(PCM_FORMAT_S16_LE) # how sound card interprets data
        self.out.setperiodsize(self.frames)



    def sinewave(self, frequency):
        self.frequency = frequency

        # note sinewave peak is limited to magnitude 0.1       
        sig = [ 0.1 * math.sin( 2.0*math.pi*self.frequency*x/self.rate ) for x in range(self.frames)]       
       
        # The scale factor for 16bit resolution
        scale = ( 2**16 - 1 )/2.0

        # Scale the signal list
        self.sig_16 = [ int(scale*x) for x in sig ]

        self.sinewave=struct.pack('<'+self.channels*self.frames*'h',*self.sig_16)
        # note above 'h' not 'l' (c type short, python integer 2) for 16 bit samples
        # with l, self.dit packed into (long) integer size=4

        # self.out.write(self.sinewave) # plays the sound in self.sinewave

    def noise(self, sigma):
        self.sigma = sigma     # Standard deviation
        mu = 0            # mean
        noise = normal(mu, sigma, self.frames)
        scale = ( 2**16 - 1 )/2.0

        # Scale the noise list
        self.noise_scaled = [ int(scale*x) for x in noise ]

        self.noiseout=struct.pack('<'+self.channels*self.frames*'h',*self.noise_scaled)
        # note above 'h' not 'l' (c type short, python integer 2) for 16 bit samples
        # with l, self.dit packed into (long) integer size=4

        # self.out.write(self.noiseout) # plays the sound in self.noiseout

#-------------------------------------------------------------------------------------------


def main():
    mysound1 = Waveform(10)
    mysound1.rate = 6000    # 6k samples per sec

    a=mysound1.noise(0.2)    # noise with 0.2 std dev
    b=mysound1.sinewave(720)# sinewave freq 720

    # add coded noise and sinewave samples
    c=audioop.add(mysound1.noiseout, mysound1.sinewave, 2)

    mysound1.out.write(c) # play unfiltered signal

    # Now add the noise and sinewave samples before structured packing
    d = [sum(pair) for pair in zip(mysound1.noise_scaled, mysound1.sig_16,)]

    d[:] = [x*0.5 for x in d] # attenuate (each sample) by 6dB


    bpf700hz = Bandpass() # create 700 hz bpf
    # Use lfilter to filter test signal with Bandpass filter.
    filtered_d = lfilter(bpf700hz.taps, 1.0, d)


    # Pack the filtered sinewave and noise
    mysound1.filterout=struct.pack('<'+mysound1.channels*mysound1.frames*'h',*filtered_d)

    # Play the filtered sound
    mysound1.out.write(mysound1.filterout)

    # open file and write filtered sound to it.
    f = open('out.raw', 'wb')
    f.write(mysound1.filterout)
    # to play file :~/python/audio$ python playbacktest.py out.raw

if __name__ == '__main__':
    main()

Comments

Popular posts from this blog

GNU Radio Waterfall and CW Filter

The following GNU radio application adds a waterfall spectrogram to the previous CW filter program. The plot show 4 CW signals in the audio band (lower sideband) at 7023 kHz. The 700Hz signal is filtered and output to the laptop headphones by the CW bandpass filter. The frequency display is shown after the script which is as follows: #!/usr/bin/env python from gnuradio import gr from gnuradio import audio from lpf_bpf_class import Bandpass from gnuradio.qtgui import qtgui from PyQt4 import QtGui import sys, sip     class cw_filter(gr.top_block):     def __init__(self):         gr.top_block.__init__(self)           sample_rate = 44100         out_rate = 8000         kaiser = Bandpass()         cw_flr = gr.fir_filter_fff(1, kaiser.bpftaps)         decimate = int(sample_rate/out_rate)         Bandpass.cutoff1 = 3000                pre_decim = Bandpass()         dec_flr = gr.fir_filter_fff(1, pre_decim.lpftaps)         dec = gr.keep_one_in_n(gr.sizeof_float, decima

Digital Bandpass Filter FIR design - Python

The python code generates the Finite Impulse Response (FIR) filter coefficients for a lowpass filter (LPF) at 10 (Hz) cut off using firwin from scipy.  A highpass filter is then created by subtracting the lowpass filter output(s) from the output of an allpass filter. To do this the coefficients of the LPF are multiplied by -1 and 1 added to the centre tap (to create the allpass filter with subtraction). A second LPF is then created with a cutoff at 15 (Hz) and the bandpass filter formed by addition of the LPF and HPF coefficients. The program also generates a test sine wave of a given amplitude and power and to this noise from a Normal distribution is added.  The graph below shows the signal and nois, and the signal (green) after filtering. The input snr is approximately 3dB. The frequency response below shows the passband centered on 12.5 (Hz), the Nyquist frequency is 50 (Hz). from numpy import cos, sin, pi, absolute, arange from numpy.random import normal from scipy.

Splunk Cheat Sheet (Linux)

1. set root's password:  sudo su passwd root Enter new UNIX password: < new_root_password > Retype new UNIX password: < new_root_password > passwd: password updated successfully # su - 2. Remove any existing Splunk directories & create user etc: # rm -rf /opt/splunkforwarder # userdel -r splunk # this will remove as above if user splunk's home directory # groupadd siem # useradd -g siem -s /bin/bash -d /home/siem -m siem # vi ~/.profile # chage -I -1 -m -0 -M -99999 -E -1 siem If above fails because of multiple passwd fails: # pam_tally --reset check with #chage -l siem # uname -a # check OS version # dpkg -i splunk-4.3.1...........intel.deb # chown -R siem:siem /opt/splunk # su - siem : $SPLUNK_HOME/bin/splunk start --accept-license : $SPLUNK_HOME/bin/splunk edit user admin -password newpassword -role admin -auth admin:changeme 3. vi ~/.profile (as follows) (OR .bash_profile) # ~/.profile: executed by the command interpreter for log