Skip to content

Commit

Permalink
Beginning of WAV code, and now call demodulate() only once
Browse files Browse the repository at this point in the history
  • Loading branch information
keithw committed Nov 1, 2011
1 parent 2430c9e commit d91f91f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
6 changes: 4 additions & 2 deletions library/au_receive.py
Expand Up @@ -56,7 +56,9 @@ def __init__( self, center_frequency, bandwidth ):
self.lowpass = Filter( 0, bandwidth )

def demodulate( self, samples ):
# Tune in band around carrier frequency
print "Running demodulate()"

# Tune in just a band around the carrier frequency
samples = self.tuner( samples )

# Shift the modulated waveform back down to baseband
Expand Down Expand Up @@ -84,4 +86,4 @@ def demodulate( self, samples ):
filtered_samples = self.lowpass( shifted_samples )

return filtered_samples

33 changes: 30 additions & 3 deletions library/au_send.py
Expand Up @@ -4,6 +4,10 @@
import math
import StringIO
import scipy.signal
import wave
import numpy
import random
import array

from au_filter import Filter
from au_defs import *
Expand All @@ -21,8 +25,8 @@
lowpass = Filter( 0, 500 )

def send( samples, stream, samples_per_chunk ):
return raw_send( modulate( samples,
samples_per_chunk ),
return raw_send( modulate_float( samples,
samples_per_chunk ),
stream )

def expand( samples, factor ):
Expand All @@ -40,7 +44,7 @@ def raw_send( chunks, stream ):
stream.write( chunk )

# Send one chunk of I samples, modulated onto the carrier frequency
def modulate( samples, samples_per_chunk ):
def modulate_float( samples, samples_per_chunk ):
global TIME
global total_sample_count
global lowpass
Expand All @@ -64,3 +68,26 @@ def modulate( samples, samples_per_chunk ):
sample_count = 0

return chunk_data

def modulate_frame( samples, existing=False ):
if existing:
if len(samples) > len(existing):
existing = numpy.hstack( (existing, numpy.zeros( len(samples) - len(existing) )) )
else:
existing = numpy.zeros( len(samples) )

sample_num = random.randint( 0, 1024 )

args = numpy.arange( sample_num, sample_num + len(samples) ) * CARRIER_CYCLES_PER_SECOND * 2 * math.pi / SAMPLES_PER_SECOND
existing += numpy.cos(args) * lowpass( samples )

return existing

def write_wav( filename, samples ):
wave_file = wave.open( filename, "w" )

wave_file.setparams( (1, 2, 8000, 0, "NONE", "NONE") )

wave_file.writeframes( array.array( 'h', [ int(0.5 + 16383.0*x) for x in samples ] ).tostring() )

wave_file.close()
27 changes: 18 additions & 9 deletions library/au_sendreceive.py
Expand Up @@ -57,15 +57,15 @@ def prepend_preamble( self, samples ):
signal.extend( [-1] * 32768 )

# prepare modulated output
samples_out = modulate( signal, SAMPLES_PER_CHUNK )
samples_out = modulate_float( signal, SAMPLES_PER_CHUNK )

return samples_out

def extract_payload( self, signal, payload_len ):
# find preamble in received signal
( preamble_start, payload_start ) = self.detect_preamble( signal )

# demodulate payload using carrier reference from preamble
# demodulate payload
slice_start = payload_start - 3*SECOND_CARRIER_LEN/4
slice_end = payload_start + payload_len
extracted_payload = self.receiver.demodulate( signal[ slice_start : slice_end ] )[ payload_start - slice_start: ]
Expand Down Expand Up @@ -101,16 +101,22 @@ def __call__( self, samples ):

return self.extract_payload( samples_all, len( samples ) )

def __init__( self ):
def __init__( self, carrier, bandwidth ):
self.id = "Audio"

self.p = pyaudio.PyAudio()

self.receiver = au_receive.Receiver( 2500, 500 )
self.carrier = carrier
self.bandwidth = bandwidth

self.receiver = au_receive.Receiver( carrier, bandwidth )

self.one = [1] * PREAMBLE_BIT_LEN
self.zero = [-1] * PREAMBLE_BIT_LEN

self.f1 = Filter( self.carrier - self.bandwidth, self.carrier + self.bandwidth )
self.f2 = Filter( 0, self.bandwidth )

def detect_preamble( self, received_signal ):
demodulation_chunk = PREAMBLE_BIT_LEN * 4

Expand All @@ -120,7 +126,7 @@ def detect_preamble( self, received_signal ):
numpy.zeros( demodulation_chunk - (len(received_signal) % demodulation_chunk) ) ) )

# first, rough demodulation
raw_received = numpy.concatenate( [self.receiver.demodulate(x) for x in numpy.split( received_signal, len(received_signal) / demodulation_chunk )] )
raw_received = numpy.concatenate( [self.dmd(x) for x in numpy.split( received_signal, len(received_signal) / demodulation_chunk )] )

searcher = Searcher( raw_received )

Expand Down Expand Up @@ -166,12 +172,10 @@ def detect_preamble( self, received_signal ):

preamble_len = preamble_end - preamble_start

# now that we've identified the payload, use one AGC setting for whole thing

# second, better demodulation
# now that we've identified the preamble, demodulate it again using a single local carrier
slice_start = preamble_start - 3*SECOND_CARRIER_LEN/4
slice_end = preamble_end + 3*SECOND_CARRIER_LEN/4
preamble_decoded = self.receiver.demodulate( received_signal[ slice_start : slice_end ] )[ preamble_start - slice_start:
preamble_decoded = self.dmd( received_signal[ slice_start : slice_end ] )[ preamble_start - slice_start:
preamble_end - slice_start ]

# find REAL phase of preamble
Expand Down Expand Up @@ -209,3 +213,8 @@ def detect_preamble( self, received_signal ):
offset_within_payload = payload_start - preamble_end

return ( preamble_start, payload_start )

def dmd( self, samples ):
args = numpy.arange(0,len(samples)) * CARRIER_CYCLES_PER_SECOND * 2 * math.pi / SAMPLES_PER_SECOND
ds = self.f1( samples ) * (numpy.cos(args) + complex(0,1) * numpy.sin(args))
return self.f2( [x.real for x in (len(samples)*ds/sum(ds) - 1) * DC/AMPLITUDE] )
2 changes: 1 addition & 1 deletion response/PS5_1.py
Expand Up @@ -32,7 +32,7 @@ def unit_step_response(channel,max_length=100):
return step_response

if __name__ == '__main__':
channel = au_sendreceive.channel()
channel = au_sendreceive.channel( 2500, 500 )

# plot the unit-sample response of our three virtual channels
# PS5_tests.plot_USR(unit_step_response(channel0),'0')
Expand Down

0 comments on commit d91f91f

Please sign in to comment.