Permalink
Browse files

Beginning of WAV code, and now call demodulate() only once

  • Loading branch information...
1 parent 2430c9e commit d91f91f10d713580cdee4a29708221497be29bab @keithw committed Nov 1, 2011
Showing with 53 additions and 15 deletions.
  1. +4 −2 library/au_receive.py
  2. +30 −3 library/au_send.py
  3. +18 −9 library/au_sendreceive.py
  4. +1 −1 response/PS5_1.py
@@ -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
@@ -84,4 +86,4 @@ def demodulate( self, samples ):
filtered_samples = self.lowpass( shifted_samples )
return filtered_samples
-
+
View
@@ -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 *
@@ -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 ):
@@ -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
@@ -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()
@@ -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: ]
@@ -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
@@ -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 )
@@ -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
@@ -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] )
View
@@ -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')

0 comments on commit d91f91f

Please sign in to comment.